Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: adds playwright testing #44

Merged
merged 24 commits into from
Jul 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
899ec5f
feat: adds playwright test to create a basic pipeline and check if it…
Michael-Kruggel Jul 12, 2024
9e37ba2
cleaning up some things
Michael-Kruggel Jul 15, 2024
a78cc15
ci: Upgraded runners
Michael-Kruggel Jul 18, 2024
191f344
maybe fix the test by expecting the baseurl instead of a /
Michael-Kruggel Jul 18, 2024
6d533ec
swapped urls
Michael-Kruggel Jul 18, 2024
6f9e398
CI debug
Michael-Kruggel Jul 18, 2024
ad2a465
Upload screenshot artifact on failure
Michael-Kruggel Jul 18, 2024
f05fb03
ci troubleshooting
Michael-Kruggel Jul 18, 2024
f22db52
ci debug
Michael-Kruggel Jul 18, 2024
a913921
added import
Michael-Kruggel Jul 18, 2024
b7c24f4
ci debug
Michael-Kruggel Jul 18, 2024
e044fdb
Made screenshot names more explicit and added new action to grab that
Michael-Kruggel Jul 18, 2024
8e4011c
lint
Michael-Kruggel Jul 18, 2024
f9a0369
CI debug
Michael-Kruggel Jul 18, 2024
2c51e5a
messing with some netpols
Michael-Kruggel Jul 18, 2024
e354d58
extra ci logging
Michael-Kruggel Jul 19, 2024
6f66b62
changed wait behavior to ensure the required secret is present
Michael-Kruggel Jul 19, 2024
c221cc4
moving secret location
Michael-Kruggel Jul 19, 2024
4b7456b
throwing stuff at the wall
Michael-Kruggel Jul 19, 2024
f21d237
Maybe uds
Michael-Kruggel Jul 19, 2024
74ecf72
remove the uds in cmd
Michael-Kruggel Jul 19, 2024
3fcfcc2
updated testing to take more screenshots
Michael-Kruggel Jul 19, 2024
a2d6084
update readme
Michael-Kruggel Jul 19, 2024
edef3b4
Update test.yaml
Michael-Kruggel Jul 19, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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