test(e2e): playwright smoke — login/create/edit/save happy path
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -19,6 +19,7 @@ frontend/dist/
|
|||||||
frontend/.vite/
|
frontend/.vite/
|
||||||
frontend/playwright-report/
|
frontend/playwright-report/
|
||||||
frontend/test-results/
|
frontend/test-results/
|
||||||
|
frontend/.pw-data/
|
||||||
|
|
||||||
# SPA build output — .gitkeep tracks the folder, everything inside is generated
|
# SPA build output — .gitkeep tracks the folder, everything inside is generated
|
||||||
src/VolcanicCore.Api/wwwroot/*
|
src/VolcanicCore.Api/wwwroot/*
|
||||||
|
|||||||
13
frontend/e2e/fixtures.ts
Normal file
13
frontend/e2e/fixtures.ts
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import { spawnSync } from "node:child_process";
|
||||||
|
import path from "node:path";
|
||||||
|
import { fileURLToPath } from "node:url";
|
||||||
|
|
||||||
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||||
|
|
||||||
|
export default async function globalSetup() {
|
||||||
|
const dataDir = path.resolve(__dirname, "../.pw-data");
|
||||||
|
// Shell out to `rm -rf` — Node's fs.rm can trip ENOTEMPTY on overlay
|
||||||
|
// filesystems (rootless containers, docker layered volumes) where the
|
||||||
|
// dir looks empty via readdir but rmdir still refuses.
|
||||||
|
spawnSync("rm", ["-rf", dataDir], { stdio: "ignore" });
|
||||||
|
}
|
||||||
27
frontend/e2e/smoke.spec.ts
Normal file
27
frontend/e2e/smoke.spec.ts
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
import { test, expect } from "@playwright/test";
|
||||||
|
|
||||||
|
test("login → create workflow → drop node → save", async ({ page }) => {
|
||||||
|
await page.goto("/login");
|
||||||
|
await page.getByLabel(/password/i).fill("hunter2");
|
||||||
|
await page.getByRole("button", { name: /sign in/i }).click();
|
||||||
|
|
||||||
|
await expect(page).toHaveURL(/\/workflows$/);
|
||||||
|
await page.getByRole("button", { name: /new workflow/i }).click();
|
||||||
|
await page.getByPlaceholder(/name/i).fill("Smoke Test");
|
||||||
|
await page.getByRole("button", { name: /^create$/i }).click();
|
||||||
|
|
||||||
|
await expect(page.getByText("Smoke Test")).toBeVisible();
|
||||||
|
await page.getByText("Smoke Test").click();
|
||||||
|
|
||||||
|
// On editor. Drag the Webhook tile onto the canvas.
|
||||||
|
const tile = page.locator("aside").filter({ hasText: /Nodes/i }).getByText("Webhook");
|
||||||
|
const canvas = page.locator(".react-flow__pane");
|
||||||
|
|
||||||
|
await tile.dragTo(canvas);
|
||||||
|
await expect(page.locator(".react-flow__node")).toHaveCount(1);
|
||||||
|
|
||||||
|
await page.getByRole("button", { name: /save/i }).click();
|
||||||
|
// No visible confirmation — reload and assert the node persisted.
|
||||||
|
await page.reload();
|
||||||
|
await expect(page.locator(".react-flow__node")).toHaveCount(1);
|
||||||
|
});
|
||||||
43
frontend/playwright.config.ts
Normal file
43
frontend/playwright.config.ts
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
import { defineConfig, devices } from "@playwright/test";
|
||||||
|
import path from "node:path";
|
||||||
|
import { fileURLToPath } from "node:url";
|
||||||
|
|
||||||
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||||
|
const dataDir = path.resolve(__dirname, "./.pw-data");
|
||||||
|
const apiPort = 5099;
|
||||||
|
const uiPort = 5173;
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
testDir: "./e2e",
|
||||||
|
timeout: 60_000,
|
||||||
|
fullyParallel: false,
|
||||||
|
workers: 1,
|
||||||
|
reporter: "list",
|
||||||
|
use: {
|
||||||
|
baseURL: `http://127.0.0.1:${uiPort}`,
|
||||||
|
trace: "off",
|
||||||
|
...devices["Desktop Chrome"],
|
||||||
|
},
|
||||||
|
webServer: [
|
||||||
|
{
|
||||||
|
// Fresh DB per run — the data dir is wiped in globalSetup.
|
||||||
|
command: `dotnet run --project ../src/VolcanicCore.Api --urls http://127.0.0.1:${apiPort}`,
|
||||||
|
cwd: __dirname,
|
||||||
|
env: {
|
||||||
|
ADMIN_PASSWORD: "hunter2",
|
||||||
|
DATA_DIRECTORY: dataDir,
|
||||||
|
},
|
||||||
|
url: `http://127.0.0.1:${apiPort}/api/health`,
|
||||||
|
timeout: 120_000,
|
||||||
|
reuseExistingServer: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
command: `pnpm dev --host 127.0.0.1 --port ${uiPort}`,
|
||||||
|
cwd: __dirname,
|
||||||
|
url: `http://127.0.0.1:${uiPort}`,
|
||||||
|
timeout: 60_000,
|
||||||
|
reuseExistingServer: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
globalSetup: "./e2e/fixtures.ts",
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user