Skip to content

Commit

Permalink
Merge pull request #44 from defenseunicorns/playwright-testing
Browse files Browse the repository at this point in the history
  • Loading branch information
Michael-Kruggel authored Jul 19, 2024
2 parents 35598aa + edef3b4 commit ae2f5a9
Show file tree
Hide file tree
Showing 14 changed files with 402 additions and 10 deletions.
39 changes: 38 additions & 1 deletion .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ permissions:
jobs:
run-test:
name: ${{ matrix.type }} ${{ matrix.flavor }}
runs-on: ubuntu-latest
runs-on: uds-marketplace-ubuntu-big-boy-8-core
timeout-minutes: 25
strategy:
matrix:
Expand Down Expand Up @@ -63,3 +63,40 @@ jobs:
uses: defenseunicorns/uds-common/.github/actions/save-logs@772b3337950b7c8e0882c527263684306bba7ce4 # v0.7.1
with:
suffix: ${{ matrix.type }}-${{ matrix.flavor }}-${{ github.run_id }}-${{ github.run_attempt }}

- name: Print cluster info
if: always()
shell: bash -e -o pipefail {0}
run: |
kubectl get nodes -o wide
- name: Print pod info
if: always()
shell: bash -e -o pipefail {0}
run: |
kubectl get pods -A -o wide
- name: Print service info
if: always()
shell: bash -e -o pipefail {0}
run: |
kubectl get svc -A -o wide
- name: Print events
if: always()
shell: bash -e -o pipefail {0}
run: |
kubectl get events -A -o wide
- name: Print Jenkins pod logs
if: always()
shell: bash -e -o pipefail {0}
run: |
kubectl logs jenkins-0 -n jenkins
- name: Upload screenshot on failure
if: failure()
uses: actions/upload-artifact@v2
with:
name: playwright-screenshot
path: tests/screenshots/*
7 changes: 6 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ defense-unicorns-distro/preflight.sh
.terraform
tmp
zarf-sbom

.vscode/
.cache/
.idea/
build/
Expand All @@ -26,3 +26,8 @@ test/tf/public-ec2-instance/.terraform
terraform.tfstate
terraform.tfstate.backup
.terraform.lock.hcl

# Tests
node_modules/
.playwright/
screenshots/
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# 🚚 UDS Jenkins Zarf Package
# 🏪 UDS Jenkins Zarf Package

[![Latest Release](https://img.shields.io/github/v/release/defenseunicorns/uds-package-jenkins)](https://github.com/defenseunicorns/uds-package-jenkins/releases)
[![Build Status](https://img.shields.io/github/actions/workflow/status/defenseunicorns/uds-package-jenkins/tag-and-release.yaml)](https://github.com/defenseunicorns/uds-package-jenkins/actions/workflows/tag-and-release.yaml)
Expand Down
18 changes: 14 additions & 4 deletions chart/templates/uds-package.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ spec:
network:
expose:
- service: jenkins
podLabels:
selector:
app.kubernetes.io/name: jenkins
gateway: tenant
host: jenkins
Expand All @@ -36,19 +36,29 @@ spec:
remoteGenerated: IntraNamespace

- direction: Egress
podLabels:
remoteGenerated: Anywhere
selector:
app.kubernetes.io/name: jenkins
port: 443
description: "Jenkins-plugins & SSO"

- direction: Egress
podLabels:
remoteNamespace: keycloak
remoteSelector:
app.kubernetes.io/name: keycloak
selector:
app.kubernetes.io/name: jenkins
port: 8080
description: "SSO Internal"

- direction: Egress
selector:
jenkins/label: jenkins-jenkins-agent
port: 443
description: "Jenkins-jobs phone home"

- direction: Egress
podLabels:
selector:
app.kubernetes.io/name: jenkins
remoteGenerated: KubeAPI

Expand Down
6 changes: 5 additions & 1 deletion common/zarf.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ metadata:
name: jenkins-common
description: "UDS jenkins Common Package"

variables:
- name: JENKINS_CLIENT_SECRET
default: ""

components:
- name: jenkins-config
required: true
Expand All @@ -22,7 +26,7 @@ components:
name: jenkins
namespace: jenkins
condition: "'{.status.phase}'=Ready"
- cmd: zarf tools kubectl get secrets sso-client-uds-package-jenkins -n jenkins -o=jsonpath='{.data.secret}' | base64 -d
- cmd: ./zarf tools kubectl get secrets sso-client-uds-package-jenkins -n jenkins -o=jsonpath='{.data.secret}' | base64 -d
mute: true
setVariables:
- name: JENKINS_CLIENT_SECRET
Expand Down
4 changes: 4 additions & 0 deletions tasks.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -62,16 +62,20 @@ tasks:
- task: create-test-bundle
- task: setup:k3d-test-cluster
- task: deploy:test-bundle
- task: setup:create-doug-user
- task: test:health-check
- task: test:ingress
- task: test:ui

- name: test-upgrade
description: Test an upgrade from the latest released package to the current branch
actions:
- task: create-latest-release-bundle
- task: setup:k3d-test-cluster
- task: deploy:test-bundle
- task: setup:create-doug-user
- task: create-test-bundle
- task: deploy:test-bundle
- task: test:health-check
- task: test:ingress
- task: test:ui
10 changes: 10 additions & 0 deletions tasks/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,13 @@ tasks:
protocol: https
address: jenkins.uds.dev/login
code: 200

- name: ui
description: Jenkins UI Checks
actions:
- cmd: npm ci
dir: tests
- cmd: npx playwright install --with-deps
dir: tests
- cmd: npx playwright test
dir: tests
43 changes: 43 additions & 0 deletions tests/auth.setup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { test as setup, expect } from '@playwright/test';
import { authFile } from './playwright.config';
import path from 'path';

// Function to generate a unique screenshot filename with a custom base name
const getUniqueScreenshotPath = (baseName: string) => {
let screenshotPath = path.resolve(__dirname, 'screenshots', `${baseName}.png`);
return screenshotPath;
};

setup('authenticate', async ({ page, context, baseURL }) => {
console.log('Current working directory:', process.cwd());
await page.goto(baseURL);
await page.getByLabel("Username or email").fill("doug");
await page.getByLabel("Password").fill("unicorn123!@#");
const screenshotPath = getUniqueScreenshotPath('beforeLogin');
console.log('Screenshot will be saved to:', screenshotPath);
await page.screenshot({ path: screenshotPath });
await page.getByRole("button", { name: "Log In" }).click();

// ensure auth cookies were set
const cookies = await context.cookies();
const keycloakCookie = cookies.find(
(cookie) => cookie.name === "KEYCLOAK_SESSION",
);

expect(keycloakCookie).toBeDefined();
expect(keycloakCookie?.value).not.toBe("");
expect(keycloakCookie?.domain).toContain("sso.");

await page.context().storageState({ path: authFile });

try {
await expect(page).toHaveURL(baseURL);
} catch (error) {
console.log('URL assertion failed');
const currentURL = page.url();
const screenshotPath = getUniqueScreenshotPath('afterLogin');
console.log('Screenshot will be saved to:', screenshotPath);
await page.screenshot({ path: screenshotPath });
throw error; // Rethrow the error after taking the screenshot
}
})
114 changes: 114 additions & 0 deletions tests/jenkins.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import { test, expect, devices } from '@playwright/test';
import path from 'path';

// Function to generate a unique screenshot filename with a custom base name
const getUniqueScreenshotPath = (baseName: string) => {
let screenshotPath = path.resolve(__dirname, 'screenshots', `${defaultBrowserType}-${baseName}.png`);
return screenshotPath;
};

let defaultBrowserType: string;

test.beforeEach(async ({ browserName }) => {
// Use browserName provided by Playwright to determine the browser type
defaultBrowserType = browserName;
});

test.describe('Jenkins Pipeline', () => {
const randomSuffix = Math.floor(Math.random() * 10000); // Generate a random number

test('Should create a simple pipeline and check its status', async ({ page, baseURL }) => {
const pipelineName = `example-pipeline-${defaultBrowserType}-${randomSuffix}`;
// Navigate to Jenkins dashboard
await page.goto(baseURL);

// Wait for the dashboard to load and verify login by checking for the logout button
await page.waitForSelector('a[href="/logout"]');
console.log('Logged in successfully using stored auth state');

// Retrieve and print cookies
const cookies = await page.context().cookies();
console.log('Cookies:', cookies);

// Wait for the "New Item" link to be visible and click it
await page.waitForSelector('a.task-link[href="/view/all/newJob"]', { timeout: 30000 });
console.log('New Item link is visible');

await page.click('a.task-link[href="/view/all/newJob"]');
console.log('Clicked on New Item link');

// Enter pipeline name
await page.waitForTimeout(2000);
await page.fill('input[name="name"]', pipelineName);
console.log(`Entered pipeline name: ${pipelineName}`);

// Select 'Pipeline' type
await page.click('li.org_jenkinsci_plugins_workflow_job_WorkflowJob');

// Verify if 'Pipeline' type is checked (aria-checked="true")
await page.waitForSelector('li.org_jenkinsci_plugins_workflow_job_WorkflowJob.active[aria-checked="true"]', { timeout: 5000 });
console.log('Pipeline job type is checked');
var screenshotPath = getUniqueScreenshotPath('job-page');
await page.screenshot({ path: screenshotPath });

// Click OK to create the pipeline
await page.click('button[type="submit"]');
console.log('Clicked OK to create the pipeline');

// Wait for the configuration page to load
await page.waitForSelector('div.jenkins-section__title#pipeline');
console.log('Configuration page loaded');

// Enter a simple pipeline script
const pipelineScript = `
pipeline {
agent any
stages {
stage('Build') {
steps {
echo 'Building...'
}
}
stage('Test') {
steps {
echo 'Testing...'
}
}
stage('Deploy') {
steps {
echo 'Deploying...'
}
}
}
}
`;
await page.waitForTimeout(2000);
await page.fill('.ace_text-input', pipelineScript);
console.log('Entered pipeline script');
await page.waitForTimeout(2000);
screenshotPath = getUniqueScreenshotPath('pipeline-page');
await page.screenshot({ path: screenshotPath });

// Save the pipeline
await page.click('button[name="Submit"]');
console.log('Saved the pipeline configuration');

// Run the pipeline
await page.click(`a[href="/job/${pipelineName}/build?delay=0sec"]`);
console.log('Triggered the pipeline build');

// Wait for the build to start and complete
await page.waitForTimeout(10000); // Wait for 10 seconds
console.log('Waited for the build to complete');

// Check the build status
await page.goto(`/job/${pipelineName}/lastBuild`);
console.log('Navigated to the last build page');

// Assert that the build was successful
await page.waitForSelector('svg[tooltip="Success"][title="Success"]', { timeout: 60000 });
console.log('Build was successful');
screenshotPath = getUniqueScreenshotPath('results-page');
await page.screenshot({ path: screenshotPath });
});
});
Loading

0 comments on commit ae2f5a9

Please sign in to comment.