add playwright e2e tests for onboarding, contact tracker
- install playwright, configure for chromium with vite dev server - add onboarding flow test: redirect, form fill, navigation to prozess - add contact tracker test: create contact, verify in list - fix onboarding form navigating to /onboarding instead of /prozess - fix date rendering crash in contact list (cast datum to text) - exclude @electric-sql/pglite from vite optimizeDeps (WASM bundle) - add test-results/, playwright-report/ to .gitignore Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
4
.gitignore
vendored
4
.gitignore
vendored
@@ -11,6 +11,10 @@ dist/
|
||||
# Mise local overrides
|
||||
.mise.local.toml
|
||||
|
||||
# Playwright
|
||||
test-results/
|
||||
playwright-report/
|
||||
|
||||
# Logs
|
||||
*.log
|
||||
|
||||
|
||||
9
bun.lock
9
bun.lock
@@ -25,6 +25,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@biomejs/biome": "^2.4.6",
|
||||
"@playwright/test": "^1.58.2",
|
||||
"@testing-library/jest-dom": "^6.9.1",
|
||||
"@testing-library/react": "^16.3.2",
|
||||
"@types/node": "^25.4.0",
|
||||
@@ -352,6 +353,8 @@
|
||||
|
||||
"@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="],
|
||||
|
||||
"@playwright/test": ["@playwright/test@1.58.2", "", { "dependencies": { "playwright": "1.58.2" }, "bin": { "playwright": "cli.js" } }, "sha512-akea+6bHYBBfA9uQqSYmlJXn61cTa+jbO87xVLCWbTqbWadRVmhxlXATaOjOgcBaWU4ePo0wB41KMFv3o35IXA=="],
|
||||
|
||||
"@radix-ui/number": ["@radix-ui/number@1.1.1", "", {}, "sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g=="],
|
||||
|
||||
"@radix-ui/primitive": ["@radix-ui/primitive@1.1.3", "", {}, "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg=="],
|
||||
@@ -1112,6 +1115,10 @@
|
||||
|
||||
"picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="],
|
||||
|
||||
"playwright": ["playwright@1.58.2", "", { "dependencies": { "playwright-core": "1.58.2" }, "optionalDependencies": { "fsevents": "2.3.2" }, "bin": { "playwright": "cli.js" } }, "sha512-vA30H8Nvkq/cPBnNw4Q8TWz1EJyqgpuinBcHET0YVJVFldr8JDNiU9LaWAE1KqSkRYazuaBhTpB5ZzShOezQ6A=="],
|
||||
|
||||
"playwright-core": ["playwright-core@1.58.2", "", { "bin": { "playwright-core": "cli.js" } }, "sha512-yZkEtftgwS8CsfYo7nm0KE8jsvm6i/PTgVtB8DL726wNf6H2IMsDuxCpJj59KDaxCtSnrWan2AeDqM7JBaultg=="],
|
||||
|
||||
"possible-typed-array-names": ["possible-typed-array-names@1.1.0", "", {}, "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg=="],
|
||||
|
||||
"postcss": ["postcss@8.5.8", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg=="],
|
||||
@@ -1480,6 +1487,8 @@
|
||||
|
||||
"micromatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
|
||||
|
||||
"playwright/fsevents": ["fsevents@2.3.2", "", { "os": "darwin" }, "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA=="],
|
||||
|
||||
"readdirp/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
|
||||
|
||||
"recast/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="],
|
||||
|
||||
29
e2e/kontakte.spec.ts
Normal file
29
e2e/kontakte.spec.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import { expect, test } from "@playwright/test";
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.goto("/onboarding");
|
||||
// Wait for PGlite to initialize and the form to render
|
||||
await page.getByLabel("Name").waitFor({ timeout: 15000 });
|
||||
|
||||
await page.getByLabel("Name").fill("Test User");
|
||||
await page.getByLabel("PLZ").fill("10115");
|
||||
await page.getByLabel("Ort").fill("Berlin");
|
||||
await page.getByLabel("Krankenkasse").fill("TK");
|
||||
await page.getByRole("button", { name: "Weiter" }).click();
|
||||
await expect(page).toHaveURL(/prozess/, { timeout: 10000 });
|
||||
});
|
||||
|
||||
test("add a new contact and see it in the list", async ({ page }) => {
|
||||
await page.getByRole("link", { name: "Kontakte" }).click();
|
||||
await expect(page).toHaveURL(/kontakte/);
|
||||
|
||||
await page.getByRole("link", { name: /Neu/ }).click();
|
||||
await expect(page).toHaveURL(/kontakte\/neu/);
|
||||
|
||||
await page.getByLabel("Name", { exact: false }).first().fill("Dr. Schmidt");
|
||||
await page.getByLabel("Stadt").fill("Berlin");
|
||||
await page.getByRole("button", { name: "Speichern" }).click();
|
||||
|
||||
await expect(page).toHaveURL(/\/kontakte$/, { timeout: 10000 });
|
||||
await expect(page.getByText("Dr. Schmidt")).toBeVisible({ timeout: 10000 });
|
||||
});
|
||||
18
e2e/onboarding.spec.ts
Normal file
18
e2e/onboarding.spec.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { expect, test } from "@playwright/test";
|
||||
|
||||
test("onboarding flow redirects new user and saves profile", async ({
|
||||
page,
|
||||
}) => {
|
||||
await page.goto("/");
|
||||
// PGlite WASM initialization takes time; wait for the redirect to complete
|
||||
await expect(page).toHaveURL(/onboarding/, { timeout: 15000 });
|
||||
|
||||
await page.getByLabel("Name").fill("Max Mustermann");
|
||||
await page.getByLabel("PLZ").fill("10115");
|
||||
await page.getByLabel("Ort").fill("Berlin");
|
||||
await page.getByLabel("Krankenkasse").fill("TK");
|
||||
await page.getByRole("button", { name: "Weiter" }).click();
|
||||
|
||||
await expect(page).toHaveURL(/prozess/, { timeout: 10000 });
|
||||
await expect(page.getByText("Dein Fortschritt")).toBeVisible();
|
||||
});
|
||||
@@ -33,6 +33,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@biomejs/biome": "^2.4.6",
|
||||
"@playwright/test": "^1.58.2",
|
||||
"@testing-library/jest-dom": "^6.9.1",
|
||||
"@testing-library/react": "^16.3.2",
|
||||
"@types/node": "^25.4.0",
|
||||
|
||||
13
playwright.config.ts
Normal file
13
playwright.config.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { defineConfig } from "@playwright/test";
|
||||
|
||||
export default defineConfig({
|
||||
testDir: "e2e",
|
||||
webServer: {
|
||||
command: "bun dev",
|
||||
port: 5173,
|
||||
reuseExistingServer: true,
|
||||
},
|
||||
use: {
|
||||
baseURL: "http://localhost:5173",
|
||||
},
|
||||
});
|
||||
@@ -25,7 +25,7 @@ export function useTherapeutenListe() {
|
||||
return useDbQuery<TherapeutMitKontakte>(`
|
||||
SELECT
|
||||
t.id, t.name, t.stadt, t.therapieform,
|
||||
(SELECT k.datum FROM kontakt k WHERE k.therapeut_id = t.id ORDER BY k.datum DESC LIMIT 1) as letzter_kontakt,
|
||||
(SELECT k.datum::text FROM kontakt k WHERE k.therapeut_id = t.id ORDER BY k.datum DESC LIMIT 1) as letzter_kontakt,
|
||||
(SELECT k.ergebnis FROM kontakt k WHERE k.therapeut_id = t.id ORDER BY k.datum DESC LIMIT 1) as letztes_ergebnis,
|
||||
(SELECT COUNT(*) FROM kontakt k WHERE k.therapeut_id = t.id) as kontakte_gesamt
|
||||
FROM therapeut t
|
||||
|
||||
@@ -30,7 +30,7 @@ export function OnboardingForm() {
|
||||
value.aktueller_schritt,
|
||||
],
|
||||
);
|
||||
navigate({ to: "/onboarding" });
|
||||
navigate({ to: "/prozess" });
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -19,6 +19,9 @@ export default defineConfig({
|
||||
manifest: false,
|
||||
}),
|
||||
],
|
||||
optimizeDeps: {
|
||||
exclude: ["@electric-sql/pglite"],
|
||||
},
|
||||
resolve: {
|
||||
alias: {
|
||||
"@": path.resolve(__dirname, "./src"),
|
||||
|
||||
Reference in New Issue
Block a user