refactor: playwright and tests in one folder
This commit is contained in:
@@ -6,6 +6,6 @@ NEXT_PUBLIC_USE_MOCK_BACKEND_LOOP_START=false
|
||||
NEXT_PUBLIC_EXPORT_STATIC=false
|
||||
NEXT_PUBLIC_USE_CGI=false
|
||||
# App-Versionsnummer
|
||||
NEXT_PUBLIC_APP_VERSION=1.6.717
|
||||
NEXT_PUBLIC_APP_VERSION=1.6.718
|
||||
NEXT_PUBLIC_CPL_MODE=json # json (Entwicklungsumgebung) oder jsSimulatedProd (CPL ->CGI-Interface-Simulator) oder production (CPL-> CGI-Interface Platzhalter)
|
||||
|
||||
|
||||
@@ -5,5 +5,5 @@ NEXT_PUBLIC_CPL_API_PATH=/CPL
|
||||
NEXT_PUBLIC_EXPORT_STATIC=true
|
||||
NEXT_PUBLIC_USE_CGI=true
|
||||
# App-Versionsnummer
|
||||
NEXT_PUBLIC_APP_VERSION=1.6.717
|
||||
NEXT_PUBLIC_APP_VERSION=1.6.718
|
||||
NEXT_PUBLIC_CPL_MODE=production
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -14,6 +14,9 @@
|
||||
/playwright-report/
|
||||
/blob-report/
|
||||
/playwright/.cache/
|
||||
playwright/report/
|
||||
playwright/test-results/
|
||||
playwright/.cache/
|
||||
|
||||
# next.js
|
||||
/.next/
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
## [1.6.718] – 2025-08-14
|
||||
|
||||
- Feat: Analogeingänge (Messwerteingänge) Modal
|
||||
|
||||
---
|
||||
## [1.6.717] – 2025-08-14
|
||||
|
||||
- feat: close button and maximize modal
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
module.exports = {
|
||||
testEnvironment: "jest-environment-jsdom",
|
||||
setupFilesAfterEnv: ["<rootDir>/jest.setup.ts"],
|
||||
testPathIgnorePatterns: ["/node_modules/", "/playwright/"],
|
||||
moduleNameMapper: {
|
||||
"\\.(css|less|scss|sass)$": "identity-obj-proxy",
|
||||
"^bootstrap-icons/font/bootstrap-icons.css$":
|
||||
|
||||
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "cpl-v4",
|
||||
"version": "1.6.717",
|
||||
"version": "1.6.718",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "cpl-v4",
|
||||
"version": "1.6.717",
|
||||
"version": "1.6.718",
|
||||
"dependencies": {
|
||||
"@fontsource/roboto": "^5.1.0",
|
||||
"@headlessui/react": "^2.2.4",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "cpl-v4",
|
||||
"version": "1.6.717",
|
||||
"version": "1.6.718",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
@@ -15,7 +15,8 @@
|
||||
"test:e2e": "playwright test",
|
||||
"test:e2e:ui": "playwright test --ui",
|
||||
"test:e2e:debug": "playwright test --debug",
|
||||
"test:e2e:report": "playwright show-report",
|
||||
"test:e2e:report": "playwright show-report playwright/report",
|
||||
"test:e2e:clean": "rimraf playwright/report playwright/test-results playwright/.cache blob-report test-results playwright-report",
|
||||
"prepare": "husky install",
|
||||
"bump-version": "node ./scripts/bumpVersion.js",
|
||||
"mocks:cable": "node ./mocks/scripts/fetchCableData.mjs --insecure",
|
||||
|
||||
@@ -4,7 +4,7 @@ import { defineConfig, devices } from "@playwright/test";
|
||||
* @see https://playwright.dev/docs/test-configuration
|
||||
*/
|
||||
export default defineConfig({
|
||||
testDir: "./tests",
|
||||
testDir: "./playwright/tests",
|
||||
/* Run tests in files in parallel */
|
||||
fullyParallel: true,
|
||||
/* Fail the build on CI if you accidentally left test.only in the source code. */
|
||||
@@ -14,7 +14,11 @@ export default defineConfig({
|
||||
/* 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",
|
||||
// Write HTML reports to a single folder under ./playwright/report
|
||||
reporter: [["html", { outputFolder: "playwright/report" }]],
|
||||
|
||||
/* Where to put test artifacts (screenshots, videos, traces, etc.) */
|
||||
outputDir: "playwright/test-results",
|
||||
/* 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('/')`. */
|
||||
|
||||
114
playwright/tests/analogInputs.spec.ts
Normal file
114
playwright/tests/analogInputs.spec.ts
Normal file
@@ -0,0 +1,114 @@
|
||||
import { test, expect } from "@playwright/test";
|
||||
/*
|
||||
Centralized location for Playwright specs.
|
||||
(Originally moved from tests/analogInputs.spec.ts)
|
||||
*/
|
||||
|
||||
test("test", async ({ page }) => {
|
||||
await page.goto("http://localhost:3000/analogInputs");
|
||||
await expect(
|
||||
page.getByRole("heading", { name: "Messwerteingänge" }).nth(1)
|
||||
).toBeVisible();
|
||||
await expect(page.getByRole("cell", { name: "Eingang" })).toBeVisible();
|
||||
await expect(page.getByRole("cell", { name: "Messwert" })).toBeVisible();
|
||||
await expect(page.getByRole("cell", { name: "Einheit" })).toBeVisible();
|
||||
await expect(page.getByRole("cell", { name: "Bezeichnung" })).toBeVisible();
|
||||
await expect(page.getByRole("cell", { name: "Einstellungen" })).toBeVisible();
|
||||
await expect(
|
||||
page.getByRole("cell", { name: "Messkurve", exact: true })
|
||||
).toBeVisible();
|
||||
await expect(page.getByText("1", { exact: true })).toBeVisible();
|
||||
await expect(page.getByText("2", { exact: true })).toBeVisible();
|
||||
await expect(page.getByText("3", { exact: true })).toBeVisible();
|
||||
await expect(
|
||||
page.getByRole("cell", { name: "4", exact: true }).locator("path")
|
||||
).toBeVisible();
|
||||
await expect(
|
||||
page.getByRole("cell", { name: "5", exact: true })
|
||||
).toBeVisible();
|
||||
await expect(page.getByText("6", { exact: true })).toBeVisible();
|
||||
await expect(
|
||||
page.getByRole("cell", { name: "7", exact: true })
|
||||
).toBeVisible();
|
||||
await expect(
|
||||
page.getByRole("cell", { name: "8", exact: true })
|
||||
).toBeVisible();
|
||||
await expect(page.locator(".border.p-2.text-center").first()).toBeVisible();
|
||||
await expect(
|
||||
page
|
||||
.getByRole("row", { name: "2 5.67 °C Temperatur" })
|
||||
.getByRole("button")
|
||||
.first()
|
||||
).toBeVisible();
|
||||
await expect(page.locator("tr:nth-child(3) > td:nth-child(5)")).toBeVisible();
|
||||
await expect(
|
||||
page
|
||||
.getByRole("row", { name: "0.01 V AE 4 Messkurve anzeigen" })
|
||||
.getByRole("button")
|
||||
.first()
|
||||
).toBeVisible();
|
||||
await expect(
|
||||
page
|
||||
.getByRole("row", { name: "8 -0.00 mA AE 8 Messkurve" })
|
||||
.getByLabel("Messkurve anzeigen")
|
||||
).toBeVisible();
|
||||
await page.getByRole("cell", { name: "1", exact: true }).click();
|
||||
await page.locator(".border.p-2.text-center").first().click();
|
||||
await expect(
|
||||
page.getByRole("heading", { name: "Einstellungen Messwerteingang" })
|
||||
).toBeVisible();
|
||||
await expect(page.getByText("Bezeichnung:")).toBeVisible();
|
||||
await expect(page.getByText("Offset:")).toBeVisible();
|
||||
await expect(page.getByText("Faktor:")).toBeVisible();
|
||||
await expect(page.getByText("Einheit:")).toBeVisible();
|
||||
await expect(page.getByText("Speicherintervall:")).toBeVisible();
|
||||
await expect(page.getByRole("button", { name: "Speichern" })).toBeVisible();
|
||||
await expect(
|
||||
page.getByRole("button", { name: "Modal schließen" })
|
||||
).toBeVisible();
|
||||
await expect(
|
||||
page.getByText(
|
||||
"Einstellungen Messwerteingang 1Bezeichnung:Offset:Faktor:Einheit:"
|
||||
)
|
||||
).toBeVisible();
|
||||
await page.getByRole("button", { name: "Modal schließen" }).click();
|
||||
await page
|
||||
.getByRole("row", { name: "1 126.63 V AE 1 Messkurve" })
|
||||
.getByLabel("Messkurve anzeigen")
|
||||
.click();
|
||||
await expect(
|
||||
page.getByText(
|
||||
"Messkurve Messwerteingang 1Eingang 1VonBisAlle MesswerteDaten laden"
|
||||
)
|
||||
).toBeVisible();
|
||||
await expect(
|
||||
page.getByRole("heading", { name: "Messkurve Messwerteingang" })
|
||||
).toBeVisible();
|
||||
await expect(page.getByText("Eingang 1VonBisAlle")).toBeVisible();
|
||||
await expect(page.getByRole("button", { name: "Daten laden" })).toBeVisible();
|
||||
await expect(
|
||||
page.getByRole("button", { name: "Alle Messwerte " })
|
||||
).toBeVisible();
|
||||
await expect(page.getByText("Von")).toBeVisible();
|
||||
await expect(page.getByText("Bis")).toBeVisible();
|
||||
await expect(page.locator("div").filter({ hasText: /^Von$/ })).toBeVisible();
|
||||
await expect(
|
||||
page.locator("div").filter({ hasText: /^Von$/ }).getByRole("textbox")
|
||||
).toBeVisible();
|
||||
await expect(page.locator("div").filter({ hasText: /^Bis$/ })).toBeVisible();
|
||||
await expect(
|
||||
page.locator("div").filter({ hasText: /^Bis$/ }).getByRole("textbox")
|
||||
).toBeVisible();
|
||||
await expect(page.getByRole("img")).toBeVisible();
|
||||
await page.getByRole("button", { name: "Alle Messwerte " }).click();
|
||||
await page.getByRole("option", { name: "Stündlich" }).click();
|
||||
await page.getByRole("button", { name: "Stündlich " }).click();
|
||||
await page.getByRole("option", { name: "Täglich" }).click();
|
||||
await page.getByRole("button", { name: "Fullscreen" }).click();
|
||||
await page.getByRole("button", { name: "Exit fullscreen" }).click();
|
||||
await expect(page.getByRole("button", { name: "Fullscreen" })).toBeVisible();
|
||||
await expect(
|
||||
page.getByRole("button", { name: "Modal schließen" })
|
||||
).toBeVisible();
|
||||
await page.getByRole("button", { name: "Modal schließen" }).click();
|
||||
});
|
||||
@@ -1,94 +0,0 @@
|
||||
import { test, expect, Page, Locator } from "@playwright/test";
|
||||
|
||||
// Helpers
|
||||
function cardByCableName(page: Page, name: string): Locator {
|
||||
// Find a module card that contains the visible cable name text
|
||||
return page.locator("div.relative.bg-gray-300", { hasText: name }).first();
|
||||
}
|
||||
|
||||
function slotOverlayIn(card: Locator): Locator {
|
||||
// Slot overlay is the only element with absolute inset-0 inside the card
|
||||
return card.locator("div.absolute.inset-0");
|
||||
}
|
||||
|
||||
async function setDeviceEvents(
|
||||
page: Page,
|
||||
{ ksx, ksy, ksz }: { ksx?: number[]; ksy?: number[]; ksz?: number[] }
|
||||
) {
|
||||
await page.evaluate(
|
||||
({ ksx, ksy, ksz }) => {
|
||||
interface W {
|
||||
loopMeasurementEvent?: number[];
|
||||
tdrMeasurementEvent?: number[];
|
||||
alignmentEvent?: number[];
|
||||
}
|
||||
const w = window as unknown as W;
|
||||
if (ksx) w.loopMeasurementEvent = ksx;
|
||||
if (ksy) w.tdrMeasurementEvent = ksy;
|
||||
if (ksz) w.alignmentEvent = ksz;
|
||||
},
|
||||
{ ksx, ksy, ksz }
|
||||
);
|
||||
}
|
||||
|
||||
// Notes:
|
||||
// - On /kabelueberwachung, the global overlay is hidden and each module shows its own overlay when active.
|
||||
// - DeviceEventsBridge polls the window arrays every 2 seconds.
|
||||
// - Dev mode serves /api/cpl/kabelueberwachungAPIHandler which initializes those arrays from mocks.
|
||||
|
||||
test.describe("Kabelüberwachung per-slot overlays", () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.goto("http://localhost:3000/kabelueberwachung");
|
||||
// Ensure page has rendered modules
|
||||
await expect(page.getByText("Rack 1")).toBeVisible();
|
||||
// Wait a moment for initial device arrays and first poll
|
||||
await page.waitForTimeout(2500);
|
||||
});
|
||||
|
||||
test("only active slot is blocked; others remain usable", async ({
|
||||
page,
|
||||
}) => {
|
||||
const card1 = cardByCableName(page, "Kabel 1"); // slot 1 (index 0) has events in mock
|
||||
const card2 = cardByCableName(page, "Kabel 2"); // slot 2 (index 1) is inactive in mock
|
||||
|
||||
// 1) Initial: overlay visible on Kabel 1, not on Kabel 2
|
||||
await expect(slotOverlayIn(card1)).toBeVisible();
|
||||
await expect(slotOverlayIn(card2)).toHaveCount(0);
|
||||
|
||||
// 2) Interact with Kabel 2 while Kabel 1 is blocked
|
||||
await expect(card2.getByRole("button", { name: "ISO" })).toBeVisible();
|
||||
await card2.getByRole("button", { name: "ISO" }).click();
|
||||
|
||||
// ISO modal should open
|
||||
await expect(page.getByText("Isolationswiderstand")).toBeVisible();
|
||||
|
||||
// Close modal with Escape
|
||||
await page.keyboard.press("Escape");
|
||||
await expect(page.getByText("Isolationswiderstand")).toHaveCount(0);
|
||||
|
||||
// 3) Dynamically switch overlay from Kabel 1 to Kabel 2
|
||||
const zero = new Array(32).fill(0);
|
||||
const ksx = zero.slice();
|
||||
ksx[1] = 1; // activate Schleife for slot 2
|
||||
await setDeviceEvents(page, { ksx });
|
||||
|
||||
// Wait for bridge poll and UI update
|
||||
await page.waitForTimeout(2500);
|
||||
|
||||
await expect(slotOverlayIn(card1)).toHaveCount(0);
|
||||
await expect(slotOverlayIn(card2)).toBeVisible();
|
||||
|
||||
// Percentage text should show in the overlay (e.g., "12%")
|
||||
await expect(slotOverlayIn(card2).getByText(/%$/)).toBeVisible();
|
||||
});
|
||||
|
||||
test("global overlay is not shown on kabelueberwachung page", async ({
|
||||
page,
|
||||
}) => {
|
||||
// A full-screen overlay would be fixed inset-0 at document level; ensure none
|
||||
const globalOverlay = page.locator(
|
||||
'div.fixed.inset-0:has-text("Bitte warten…")'
|
||||
);
|
||||
await expect(globalOverlay).toHaveCount(0);
|
||||
});
|
||||
});
|
||||
@@ -1,78 +0,0 @@
|
||||
import { test, expect, Page } from "@playwright/test";
|
||||
|
||||
// Simple visual smoke test for /kabelueberwachung
|
||||
// Creates / compares a full-page screenshot (baseline generated on first run with --update-snapshots)
|
||||
// To update baseline: npx playwright test tests/kabelueberwachung-visual.spec.ts --update-snapshots
|
||||
// To run in UI mode: npx playwright test --ui
|
||||
|
||||
// Helper to stabilize dynamic UI before screenshot
|
||||
|
||||
test.describe("Kabelüberwachung Visual", () => {
|
||||
test("test", async ({ page }) => {
|
||||
// Globales Auto-Highlight für jeden Klick (nur lokale Debug-Hilfe)
|
||||
await page.addInitScript(() => {
|
||||
interface HighlightFlagWindow extends Window {
|
||||
__PW_CLICK_HIGHLIGHT__?: boolean;
|
||||
}
|
||||
const w = window as HighlightFlagWindow;
|
||||
if (w.__PW_CLICK_HIGHLIGHT__) return; // einmalig
|
||||
w.__PW_CLICK_HIGHLIGHT__ = true;
|
||||
document.addEventListener(
|
||||
"click",
|
||||
(ev) => {
|
||||
const el = ev.target as HTMLElement | null;
|
||||
if (!el || !(el instanceof HTMLElement)) return;
|
||||
const prev = el.style.outline;
|
||||
el.style.outline = "3px solid #ff00aa";
|
||||
setTimeout(() => {
|
||||
el.style.outline = prev;
|
||||
}, 600);
|
||||
},
|
||||
true // capture, damit nichts das Event vorher stoppt
|
||||
);
|
||||
});
|
||||
await page.goto("http://localhost:3000/kabelueberwachung");
|
||||
await page
|
||||
.locator(".bg-littwin-blue.text-white.text-\\[0\\.625rem\\]")
|
||||
.first()
|
||||
.click();
|
||||
//warte 1 Sekunde
|
||||
await page.waitForTimeout(2000);
|
||||
await page.getByRole("button", { name: "Daten laden" }).click();
|
||||
await page.waitForTimeout(2000);
|
||||
await page.getByRole("button", { name: "Messkurve" }).click();
|
||||
await page.waitForTimeout(2000);
|
||||
await page.getByRole("option", { name: "Meldungen" }).click();
|
||||
await page.waitForTimeout(2000);
|
||||
await page.getByRole("button", { name: "" }).click();
|
||||
await page.waitForTimeout(2000);
|
||||
page.once("dialog", (dialog) => {
|
||||
console.log(`Dialog message: ${dialog.message()}`);
|
||||
dialog.dismiss().catch(() => {});
|
||||
});
|
||||
await page.waitForTimeout(2000);
|
||||
await page.locator(".flex > button:nth-child(2)").first().click();
|
||||
await page.waitForTimeout(2000);
|
||||
await page.getByRole("button", { name: "Messkurve" }).click();
|
||||
await page.waitForTimeout(2000);
|
||||
await page.getByRole("option", { name: "Meldungen" }).click();
|
||||
await page.waitForTimeout(2000);
|
||||
await page.getByRole("button", { name: "" }).click();
|
||||
await page.waitForTimeout(2000);
|
||||
await page
|
||||
.locator(".bg-littwin-blue.text-white.cursor-pointer")
|
||||
.first()
|
||||
.click();
|
||||
await page.waitForTimeout(2000);
|
||||
await page.getByRole("button", { name: "Messkurve" }).click();
|
||||
await page.waitForTimeout(2000);
|
||||
await page.getByRole("option", { name: "Meldungen" }).click();
|
||||
await page.waitForTimeout(2000);
|
||||
await page.getByRole("button", { name: "" }).click();
|
||||
await page.waitForTimeout(2000);
|
||||
});
|
||||
});
|
||||
//zum ausführen
|
||||
// npx playwright test kabelueberwachung-visual.spec.ts --project=chromium --headed
|
||||
//zum aufzeichnen
|
||||
// npx playwright codegen http://localhost:3000/kabelueberwachung --channel=chrome
|
||||
Reference in New Issue
Block a user