From 71474b2b41a57e3448f4d82717cd7075624a0649 Mon Sep 17 00:00:00 2001 From: Torun Date: Mon, 11 May 2026 10:59:24 +0200 Subject: [PATCH 1/4] test: add playwright end to end test --- README.md | 8 ++- frontend/.github/workflows/playwright.yml | 34 +++++++++++++ frontend/.gitignore | 7 +++ frontend/e2e/homepage.spec.ts | 16 ++++++ frontend/package.json | 4 +- frontend/playwright.config.ts | 59 +++++++++++++++++++++++ frontend/pnpm-lock.yaml | 38 +++++++++++++++ frontend/pnpm-workspace.yaml | 2 + pnpm-lock.yaml | 43 +++++++++++++++++ 9 files changed, 208 insertions(+), 3 deletions(-) create mode 100644 frontend/.github/workflows/playwright.yml create mode 100644 frontend/e2e/homepage.spec.ts create mode 100644 frontend/playwright.config.ts create mode 100644 frontend/pnpm-workspace.yaml create mode 100644 pnpm-lock.yaml diff --git a/README.md b/README.md index 99aff3d..5e09968 100644 --- a/README.md +++ b/README.md @@ -16,10 +16,14 @@ cd fastapi-vue-spa-boilerplate # Backend cd backend && source .venv/bin/activate && uvicorn app.main:app --reload -# Frontend +# Frontend cd frontend && pnpm dev + +# E2E testing +cd frontend && pnpm test:e2e + ``` - Frontend: http://localhost:3000 - Backend: http://localhost:8000 -- API Docs: http://localhost:8000/docs \ No newline at end of file +- API Docs: http://localhost:8000/docs diff --git a/frontend/.github/workflows/playwright.yml b/frontend/.github/workflows/playwright.yml new file mode 100644 index 0000000..3f380c7 --- /dev/null +++ b/frontend/.github/workflows/playwright.yml @@ -0,0 +1,34 @@ +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/* + - uses: actions/setup-python@v5 + with: + python-version: "3.12" + + - name: Install frontend dependencies + run: npm install -g pnpm && pnpm install + + - name: Install backend dependencies + run: pip install -r backend/requirements.txt + - name: Install Playwright Browsers + run: pnpm exec playwright install --with-deps + - name: Run Playwright tests + run: pnpm exec 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 index a547bf3..2e5968d 100644 --- a/frontend/.gitignore +++ b/frontend/.gitignore @@ -22,3 +22,10 @@ dist-ssr *.njsproj *.sln *.sw? + +# Playwright +/test-results/ +/playwright-report/ +/blob-report/ +/playwright/.cache/ +/playwright/.auth/ diff --git a/frontend/e2e/homepage.spec.ts b/frontend/e2e/homepage.spec.ts new file mode 100644 index 0000000..cf6eeba --- /dev/null +++ b/frontend/e2e/homepage.spec.ts @@ -0,0 +1,16 @@ +import { test, expect } from "@playwright/test"; + +test("should display the correct page title", async ({ page }) => { + await page.goto("/"); + + await expect(page).toHaveTitle("Vite + Vue + TS"); +}); + +test("should display backend health status", async ({ page }) => { + await page.goto("/"); + + const healthStatus = page.getByRole("paragraph"); + await expect(healthStatus).toHaveText( + 'Health: {"status":"healthy","message":"FastAPI backend is running","environment":"development","version":"1.0.0"}', + ); +}); diff --git a/frontend/package.json b/frontend/package.json index 50413a9..3160739 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -3,12 +3,14 @@ "version": "0.0.0", "scripts": { "dev": "vite", - "build": "vite build" + "build": "vite build", + "test:e2e": "pnpm exec playwright test" }, "dependencies": { "vue": "^3.4.0" }, "devDependencies": { + "@playwright/test": "^1.59.1", "@types/node": "^24.3.0", "@vitejs/plugin-vue": "^4.5.0", "@vue/tsconfig": "^0.8.1", diff --git a/frontend/playwright.config.ts b/frontend/playwright.config.ts new file mode 100644 index 0000000..b40c16e --- /dev/null +++ b/frontend/playwright.config.ts @@ -0,0 +1,59 @@ +import { defineConfig, devices } from "@playwright/test"; +import path from "path"; + +const absolutePathBackend = path.resolve(__dirname, "../backend"); + +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:5173", + + /* 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"] }, + }, + ], + + /* Run your local dev server before starting the tests */ + webServer: [ + { + command: `cd ${absolutePathBackend} && source .venv/bin/activate && uvicorn app.main:app --host 127.0.0.1 --port 8000`, + url: "http://127.0.0.1:8000", + reuseExistingServer: !process.env.CI, + }, + { + command: "pnpm dev --host 0.0.0.0", + url: "http://127.0.0.1:5173", + reuseExistingServer: !process.env.CI, + }, + ], +}); diff --git a/frontend/pnpm-lock.yaml b/frontend/pnpm-lock.yaml index 82d4331..fffbf73 100644 --- a/frontend/pnpm-lock.yaml +++ b/frontend/pnpm-lock.yaml @@ -12,6 +12,9 @@ importers: specifier: ^3.4.0 version: 3.5.20(typescript@5.9.2) devDependencies: + '@playwright/test': + specifier: ^1.59.1 + version: 1.59.1 '@types/node': specifier: ^24.3.0 version: 24.3.0 @@ -185,6 +188,11 @@ packages: '@jridgewell/sourcemap-codec@1.5.5': resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} + '@playwright/test@1.59.1': + resolution: {integrity: sha512-PG6q63nQg5c9rIi4/Z5lR5IVF7yU5MqmKaPOe0HSc0O2cX1fPi96sUQu5j7eo4gKCkB2AnNGoWt7y4/Xx3Kcqg==} + engines: {node: '>=18'} + hasBin: true + '@types/node@24.3.0': resolution: {integrity: sha512-aPTXCrfwnDLj4VvXrm+UUCQjNEvJgNA8s5F1cvwQU+3KNltTOkBm1j30uNLyqqPNe7gE3KFzImYoZEfLhp4Yow==} @@ -250,6 +258,11 @@ packages: estree-walker@2.0.2: resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + fsevents@2.3.2: + resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} @@ -266,6 +279,16 @@ packages: picocolors@1.1.1: resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + playwright-core@1.59.1: + resolution: {integrity: sha512-HBV/RJg81z5BiiZ9yPzIiClYV/QMsDCKUyogwH9p3MCP6IYjUFu/MActgYAvK0oWyV9NlwM3GLBjADyWgydVyg==} + engines: {node: '>=18'} + hasBin: true + + playwright@1.59.1: + resolution: {integrity: sha512-C8oWjPR3F81yljW9o5OxcWzfh6avkVwDD2VYdwIGqTkl+OGFISgypqzfu7dOe4QNLL2aqcWBmI3PMtLIK233lw==} + engines: {node: '>=18'} + hasBin: true + postcss@8.5.6: resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} engines: {node: ^10 || ^12 || >=14} @@ -406,6 +429,10 @@ snapshots: '@jridgewell/sourcemap-codec@1.5.5': {} + '@playwright/test@1.59.1': + dependencies: + playwright: 1.59.1 + '@types/node@24.3.0': dependencies: undici-types: 7.10.0 @@ -505,6 +532,9 @@ snapshots: estree-walker@2.0.2: {} + fsevents@2.3.2: + optional: true + fsevents@2.3.3: optional: true @@ -516,6 +546,14 @@ snapshots: picocolors@1.1.1: {} + playwright-core@1.59.1: {} + + playwright@1.59.1: + dependencies: + playwright-core: 1.59.1 + optionalDependencies: + fsevents: 2.3.2 + postcss@8.5.6: dependencies: nanoid: 3.3.11 diff --git a/frontend/pnpm-workspace.yaml b/frontend/pnpm-workspace.yaml new file mode 100644 index 0000000..5ed0b5a --- /dev/null +++ b/frontend/pnpm-workspace.yaml @@ -0,0 +1,2 @@ +allowBuilds: + esbuild: true diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..85d7848 --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,43 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + playwright: + specifier: ^1.59.1 + version: 1.59.1 + +packages: + + fsevents@2.3.2: + resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + playwright-core@1.59.1: + resolution: {integrity: sha512-HBV/RJg81z5BiiZ9yPzIiClYV/QMsDCKUyogwH9p3MCP6IYjUFu/MActgYAvK0oWyV9NlwM3GLBjADyWgydVyg==} + engines: {node: '>=18'} + hasBin: true + + playwright@1.59.1: + resolution: {integrity: sha512-C8oWjPR3F81yljW9o5OxcWzfh6avkVwDD2VYdwIGqTkl+OGFISgypqzfu7dOe4QNLL2aqcWBmI3PMtLIK233lw==} + engines: {node: '>=18'} + hasBin: true + +snapshots: + + fsevents@2.3.2: + optional: true + + playwright-core@1.59.1: {} + + playwright@1.59.1: + dependencies: + playwright-core: 1.59.1 + optionalDependencies: + fsevents: 2.3.2 From f4aa70726d22eb3617364eb3a482c0474bbd2b2b Mon Sep 17 00:00:00 2001 From: Torun Date: Mon, 11 May 2026 11:19:24 +0200 Subject: [PATCH 2/4] fix: move GitHub Actions workflow to repository root --- {frontend/.github => .github}/workflows/playwright.yml | 0 frontend/playwright.config.ts | 10 ---------- 2 files changed, 10 deletions(-) rename {frontend/.github => .github}/workflows/playwright.yml (100%) diff --git a/frontend/.github/workflows/playwright.yml b/.github/workflows/playwright.yml similarity index 100% rename from frontend/.github/workflows/playwright.yml rename to .github/workflows/playwright.yml diff --git a/frontend/playwright.config.ts b/frontend/playwright.config.ts index b40c16e..f216d51 100644 --- a/frontend/playwright.config.ts +++ b/frontend/playwright.config.ts @@ -6,26 +6,16 @@ const absolutePathBackend = path.resolve(__dirname, "../backend"); 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:5173", - - /* 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", From eee25292782999faa82012470d13ccc852fba0c6 Mon Sep 17 00:00:00 2001 From: Torun Date: Mon, 11 May 2026 12:54:16 +0200 Subject: [PATCH 3/4] fix: use Playwright webServer for CI test setup --- frontend/playwright.config.ts | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/frontend/playwright.config.ts b/frontend/playwright.config.ts index f216d51..adc65c4 100644 --- a/frontend/playwright.config.ts +++ b/frontend/playwright.config.ts @@ -13,7 +13,6 @@ export default defineConfig({ reporter: "html", use: { baseURL: "http://127.0.0.1:5173", - trace: "on-first-retry", }, projects: [ @@ -33,17 +32,15 @@ export default defineConfig({ }, ], - /* Run your local dev server before starting the tests */ + /* Run your local dev server before starting the tests*/ webServer: [ { - command: `cd ${absolutePathBackend} && source .venv/bin/activate && uvicorn app.main:app --host 127.0.0.1 --port 8000`, + command: `cd ${absolutePathBackend} && uvicorn app.main:app --host 127.0.0.1 --port 8000`, url: "http://127.0.0.1:8000", - reuseExistingServer: !process.env.CI, }, { command: "pnpm dev --host 0.0.0.0", url: "http://127.0.0.1:5173", - reuseExistingServer: !process.env.CI, }, ], }); From ac1d6d607dd6755d0b56e7ab142a9841dfed6bc7 Mon Sep 17 00:00:00 2001 From: Torun Date: Mon, 11 May 2026 13:06:19 +0200 Subject: [PATCH 4/4] fix(ci): fix frontend dependency install path --- .github/workflows/playwright.yml | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index 3f380c7..d8c5e3f 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -16,19 +16,32 @@ jobs: - uses: actions/setup-python@v5 with: python-version: "3.12" + - name: List repo structure + run: ls -R + #backend setup and start + - name: Install backend dependencies + working-directory: backend + run: pip install -r requirements.txt + + #frontend setup and run + - name: Setup pnpm + run: npm install -g pnpm - name: Install frontend dependencies - run: npm install -g pnpm && pnpm install + working-directory: frontend + run: pnpm install - - name: Install backend dependencies - run: pip install -r backend/requirements.txt + #Playwright setup and run tests - name: Install Playwright Browsers + working-directory: frontend run: pnpm exec playwright install --with-deps + - name: Run Playwright tests + working-directory: frontend run: pnpm exec playwright test - uses: actions/upload-artifact@v4 if: ${{ !cancelled() }} with: name: playwright-report - path: playwright-report/ + path: frontend/playwright-report/ retention-days: 30