From b94f6c48239220c3f40877e614099a60b34aa25c Mon Sep 17 00:00:00 2001 From: soGit Date: Thu, 31 Oct 2024 23:25:15 +0000 Subject: [PATCH] chore: Add Playwright testing framework and configuration Signed-off-by: soGit --- frontend/.github/workflows/playwright.yml | 27 ++ frontend/.gitignore | 5 + frontend/e2e/dashboard.spec.ts | 67 +++ frontend/package-lock.json | 74 +++ frontend/package.json | 9 +- frontend/playwright.config.ts | 79 ++++ .../footer-bar/footer-bar.component.html | 6 +- frontend/tests-examples/demo-todo-app.spec.ts | 437 ++++++++++++++++++ 8 files changed, 698 insertions(+), 6 deletions(-) create mode 100644 frontend/.github/workflows/playwright.yml create mode 100644 frontend/.gitignore create mode 100644 frontend/e2e/dashboard.spec.ts create mode 100644 frontend/playwright.config.ts create mode 100644 frontend/tests-examples/demo-todo-app.spec.ts diff --git a/frontend/.github/workflows/playwright.yml b/frontend/.github/workflows/playwright.yml new file mode 100644 index 0000000..3eb1314 --- /dev/null +++ b/frontend/.github/workflows/playwright.yml @@ -0,0 +1,27 @@ +name: Playwright Tests +on: + push: + branches: [ main, master ] + pull_request: + branches: [ main, master ] +jobs: + test: + timeout-minutes: 60 + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: lts/* + - name: Install dependencies + run: npm ci + - name: Install Playwright Browsers + run: npx playwright install --with-deps + - name: Run Playwright tests + run: npx playwright test + - uses: actions/upload-artifact@v4 + if: ${{ !cancelled() }} + with: + name: playwright-report + path: playwright-report/ + retention-days: 30 diff --git a/frontend/.gitignore b/frontend/.gitignore new file mode 100644 index 0000000..68c5d18 --- /dev/null +++ b/frontend/.gitignore @@ -0,0 +1,5 @@ +node_modules/ +/test-results/ +/playwright-report/ +/blob-report/ +/playwright/.cache/ diff --git a/frontend/e2e/dashboard.spec.ts b/frontend/e2e/dashboard.spec.ts new file mode 100644 index 0000000..d783490 --- /dev/null +++ b/frontend/e2e/dashboard.spec.ts @@ -0,0 +1,67 @@ +import { test, expect } from "@playwright/test"; + +test.describe("Landing page", () => { + let page; + + test.beforeEach(async ({ browser }) => { + page = await browser.newPage(); + await page.goto("http://localhost:4200"); + }); + + test("should not has error logs", async ({ page }) => { + const logs = []; + page.on("console", (msg) => { + if (msg.type() === "error") { + logs.push(msg); + } + }); + expect(logs.length).toBe(0); + }); + + test("should display welcome message", async () => { + const title = await page.textContent("h1"); + expect(title).toBe("Welcome to Hub Microcks.io"); + }); + + test("should display 'Contribute' button", async () => { + const button = await page.textContent("button"); + expect(button).toContain("Contribute"); + }); + + test("should display 'Submit your mocks' link", async () => { + await page.goto("http://localhost:4200/"); + await page.getByRole("link", { name: "Submit your mocks >" }).click(); + await expect(page.locator("h1")).toContainText( + "How to contribute an API package" + ); + }); + + test.describe("Contribute button", () => { + test("should display 'Contribute' button actions", async () => { + await page.goto("http://localhost:4200/"); + await page.getByRole("button", { name: "Contribute" }).click(); + await expect(page.getByLabel("Contribute")).toContainText("Overview"); + await expect(page.getByLabel("Contribute")).toContainText( + "Create API mocks and tests suite" + ); + await expect(page.getByLabel("Contribute")).toContainText( + "Package your API mocks and tests" + ); + await expect(page.getByLabel("Contribute")).toContainText( + "Submit your API package" + ); + }); + }); + + test.describe("Microcks.io", () => { + test("should display 'Jump-start with Microcks' link", async () => { + await page.goto("http://localhost:4200/"); + await page + .getByRole("link", { name: "Jump-start with Microcks" }) + .click(); + const bodyText = await page.textContent("body"); + expect(bodyText).not.toContain("Page Not Fount"); + expect(bodyText).not.toContain("404"); + }); + }); +}); diff --git a/frontend/package-lock.json b/frontend/package-lock.json index df51475..daabb30 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -35,6 +35,7 @@ "@angular/cli": "~8.3.29", "@angular/compiler-cli": "~8.2.14", "@angular/language-service": "~8.2.14", + "@playwright/test": "^1.48.2", "@types/jasmine": "~3.10.18", "@types/jasminewd2": "~2.0.13", "@types/node": "~8.9.5", @@ -1077,6 +1078,22 @@ "webpack": "^4.0.0" } }, + "node_modules/@playwright/test": { + "version": "1.48.2", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.48.2.tgz", + "integrity": "sha512-54w1xCWfXuax7dz4W2M9uw0gDyh+ti/0K/MxcCUxChFh37kkdxPdfZDw5QBbuPUJHr1CiHJ1hXgSs+GgeQc5Zw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright": "1.48.2" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/@schematics/angular": { "version": "8.3.29", "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-8.3.29.tgz", @@ -8905,6 +8922,38 @@ "node": ">=6" } }, + "node_modules/playwright": { + "version": "1.48.2", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.48.2.tgz", + "integrity": "sha512-NjYvYgp4BPmiwfe31j4gHLa3J7bD2WiBz8Lk2RoSsmX38SVIARZ18VYjxLjAcDsAhA+F4iSEXTSGgjua0rrlgQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright-core": "1.48.2" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.48.2", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.48.2.tgz", + "integrity": "sha512-sjjw+qrLFlriJo64du+EK0kJgZzoQPsabGF4lBvsid+3CNIZIYLgnMj9V6JY5VhM2Peh20DJWIVpVljLLnlawA==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/popper.js": { "version": "1.16.1", "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz", @@ -14012,6 +14061,15 @@ "webpack-sources": "1.3.0" } }, + "@playwright/test": { + "version": "1.48.2", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.48.2.tgz", + "integrity": "sha512-54w1xCWfXuax7dz4W2M9uw0gDyh+ti/0K/MxcCUxChFh37kkdxPdfZDw5QBbuPUJHr1CiHJ1hXgSs+GgeQc5Zw==", + "dev": true, + "requires": { + "playwright": "1.48.2" + } + }, "@schematics/angular": { "version": "8.3.29", "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-8.3.29.tgz", @@ -20412,6 +20470,22 @@ "find-up": "^3.0.0" } }, + "playwright": { + "version": "1.48.2", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.48.2.tgz", + "integrity": "sha512-NjYvYgp4BPmiwfe31j4gHLa3J7bD2WiBz8Lk2RoSsmX38SVIARZ18VYjxLjAcDsAhA+F4iSEXTSGgjua0rrlgQ==", + "dev": true, + "requires": { + "fsevents": "2.3.2", + "playwright-core": "1.48.2" + } + }, + "playwright-core": { + "version": "1.48.2", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.48.2.tgz", + "integrity": "sha512-sjjw+qrLFlriJo64du+EK0kJgZzoQPsabGF4lBvsid+3CNIZIYLgnMj9V6JY5VhM2Peh20DJWIVpVljLLnlawA==", + "dev": true + }, "popper.js": { "version": "1.16.1", "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz", diff --git a/frontend/package.json b/frontend/package.json index 482ca99..b6c8ff2 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -10,7 +10,9 @@ "build-prod": "ng build --prod", "test": "ng test", "lint": "ng lint", - "e2e": "ng e2e" + "e2e": "playwright test", + "e2e:report": "playwright show-report", + "e2e:ui-mode": "playwright test --ui" }, "private": true, "dependencies": { @@ -40,9 +42,10 @@ "@angular/cli": "~8.3.29", "@angular/compiler-cli": "~8.2.14", "@angular/language-service": "~8.2.14", - "@types/node": "~8.9.5", + "@playwright/test": "^1.48.2", "@types/jasmine": "~3.10.18", "@types/jasminewd2": "~2.0.13", + "@types/node": "~8.9.5", "codelyzer": "^5.2.2", "jasmine-core": "~3.99.1", "jasmine-spec-reporter": "~4.2.1", @@ -56,4 +59,4 @@ "tslint": "~5.15.0", "typescript": "~3.5.3" } -} +} \ No newline at end of file diff --git a/frontend/playwright.config.ts b/frontend/playwright.config.ts new file mode 100644 index 0000000..efd9b88 --- /dev/null +++ b/frontend/playwright.config.ts @@ -0,0 +1,79 @@ +import { defineConfig, devices } from '@playwright/test'; + +/** + * Read environment variables from file. + * https://github.com/motdotla/dotenv + */ +// import dotenv from 'dotenv'; +// import path from 'path'; +// dotenv.config({ path: path.resolve(__dirname, '.env') }); + +/** + * See https://playwright.dev/docs/test-configuration. + */ +export default defineConfig({ + testDir: './e2e', + /* Run tests in files in parallel */ + fullyParallel: true, + /* Fail the build on CI if you accidentally left test.only in the source code. */ + forbidOnly: !!process.env.CI, + /* Retry on CI only */ + retries: process.env.CI ? 2 : 0, + /* Opt out of parallel tests on CI. */ + workers: process.env.CI ? 1 : undefined, + /* Reporter to use. See https://playwright.dev/docs/test-reporters */ + reporter: 'html', + /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ + use: { + /* Base URL to use in actions like `await page.goto('/')`. */ + // baseURL: 'http://127.0.0.1:3000', + + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: 'on-first-retry', + }, + + /* Configure projects for major browsers */ + projects: [ + { + name: 'chromium', + use: { ...devices['Desktop Chrome'] }, + }, + + { + name: 'firefox', + use: { ...devices['Desktop Firefox'] }, + }, + + { + name: 'webkit', + use: { ...devices['Desktop Safari'] }, + }, + + /* Test against mobile viewports. */ + // { + // name: 'Mobile Chrome', + // use: { ...devices['Pixel 5'] }, + // }, + // { + // name: 'Mobile Safari', + // use: { ...devices['iPhone 12'] }, + // }, + + /* Test against branded browsers. */ + // { + // name: 'Microsoft Edge', + // use: { ...devices['Desktop Edge'], channel: 'msedge' }, + // }, + // { + // name: 'Google Chrome', + // use: { ...devices['Desktop Chrome'], channel: 'chrome' }, + // }, + ], + + /* Run your local dev server before starting the tests */ + // webServer: { + // command: 'npm run start', + // url: 'http://127.0.0.1:3000', + // reuseExistingServer: !process.env.CI, + // }, +}); diff --git a/frontend/src/app/components/footer-bar/footer-bar.component.html b/frontend/src/app/components/footer-bar/footer-bar.component.html index 8020c0b..2a32877 100644 --- a/frontend/src/app/components/footer-bar/footer-bar.component.html +++ b/frontend/src/app/components/footer-bar/footer-bar.component.html @@ -10,7 +10,7 @@

List your API mocks on Hub.microcks.io

- Jump-start with Microcks + Jump-start with Microcks