diff --git a/.env.development b/.env.development index 8c3aa39..60804eb 100644 --- a/.env.development +++ b/.env.development @@ -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.831 +NEXT_PUBLIC_APP_VERSION=1.6.832 NEXT_PUBLIC_CPL_MODE=json # json (Entwicklungsumgebung) oder jsSimulatedProd (CPL ->CGI-Interface-Simulator) oder production (CPL-> CGI-Interface Platzhalter) diff --git a/.env.production b/.env.production index 4319b5a..f45a01d 100644 --- a/.env.production +++ b/.env.production @@ -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.831 +NEXT_PUBLIC_APP_VERSION=1.6.832 NEXT_PUBLIC_CPL_MODE=production \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index e604ed9..34181c5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +## [1.6.832] – 2025-09-03 + +- refactoring: test files + +--- ## [1.6.831] – 2025-09-03 - fix: DigitalOutputsVies.tsx diff --git a/mocks/device-cgi-simulator/SERVICE/digitalOutputsMockData.json b/mocks/device-cgi-simulator/SERVICE/digitalOutputsMockData.json index 1967e01..42fdc84 100644 --- a/mocks/device-cgi-simulator/SERVICE/digitalOutputsMockData.json +++ b/mocks/device-cgi-simulator/SERVICE/digitalOutputsMockData.json @@ -1,9 +1,9 @@ { "win_da_state": [ - 0, - 0, - 0, - 0 + 1, + 1, + 1, + 1 ], "win_da_bezeichnung": [ "Ausgang1", diff --git a/package-lock.json b/package-lock.json index 3907bbc..f1e461a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "cpl-v4", - "version": "1.6.831", + "version": "1.6.832", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "cpl-v4", - "version": "1.6.831", + "version": "1.6.832", "dependencies": { "@fontsource/roboto": "^5.1.0", "@headlessui/react": "^2.2.4", diff --git a/package.json b/package.json index ba0f2a1..2732aef 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cpl-v4", - "version": "1.6.831", + "version": "1.6.832", "private": true, "scripts": { "dev": "next dev -p 3000", @@ -20,6 +20,7 @@ "test:e2e:webkit": "playwright test --project=webkit", "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", + "test:e2e:missing": "node ./scripts/find-missing-playwright-tests.mjs", "prepare": "husky install", "bump-version": "node ./scripts/bumpVersion.js", "mocks:cable": "node ./mocks/scripts/fetchCableData.mjs --insecure", diff --git a/playwright/components/main/analogInputs/analogInputsChartModalTest.ts b/playwright/components/main/analogInputs/analogInputsChartModalTest.ts new file mode 100644 index 0000000..8713aa0 --- /dev/null +++ b/playwright/components/main/analogInputs/analogInputsChartModalTest.ts @@ -0,0 +1,19 @@ +import { test, expect } from "@playwright/test"; +import { highlightAndExpectVisible } from "@playwright/utils/highlight"; + +test("AnalogInputsChartModal opens after clicking chart button", async ({ + page, +}) => { + await page.goto("/analogInputs"); + // Öffne Modal via Chart-Button (📈) + await highlightAndExpectVisible( + page, + page.getByRole("button", { name: "Messkurve anzeigen" }) + ); + await page + .getByRole("button", { name: "Messkurve anzeigen" }) + .first() + .click(); + await highlightAndExpectVisible(page, page.getByRole("dialog")); + await expect(page.getByRole("dialog")).toBeVisible(); +}); diff --git a/playwright/components/main/analogInputs/analogInputsDatePickerTest.ts b/playwright/components/main/analogInputs/analogInputsDatePickerTest.ts new file mode 100644 index 0000000..11d2e4f --- /dev/null +++ b/playwright/components/main/analogInputs/analogInputsDatePickerTest.ts @@ -0,0 +1,15 @@ +import { test } from "@playwright/test"; +import { highlightAndExpectVisible } from "@playwright/utils/highlight"; + +test("AnalogInputsDatePicker renders two inputs", async ({ page }) => { + await page.goto("/analogInputs"); + // Öffne erst die Chart-Ansicht (enthält den DatePicker) + const chartBtn = page + .getByRole("button", { name: "Messkurve anzeigen" }) + .first(); + await highlightAndExpectVisible(page, chartBtn); + await chartBtn.click(); + await highlightAndExpectVisible(page, page.getByRole("dialog")); + await highlightAndExpectVisible(page, page.getByText("Von")); + await highlightAndExpectVisible(page, page.getByText("Bis")); +}); diff --git a/playwright/components/main/analogInputs/analogInputsSettingsModalTest.ts b/playwright/components/main/analogInputs/analogInputsSettingsModalTest.ts new file mode 100644 index 0000000..21a1378 --- /dev/null +++ b/playwright/components/main/analogInputs/analogInputsSettingsModalTest.ts @@ -0,0 +1,17 @@ +import { test } from "@playwright/test"; +import { highlightAndExpectVisible } from "@playwright/utils/highlight"; + +test("AnalogInputsSettingsModal opens after clicking settings", async ({ + page, +}) => { + await page.goto("/analogInputs"); + // Wähle die erste Tabellenzeile und in der 5. Spalte (Einstellungen) den Button + const firstRow = page.locator("table tbody tr").first(); + const settingsButton = firstRow.locator("td").nth(4).locator("button"); + await highlightAndExpectVisible(page, settingsButton); + await settingsButton.click(); + await highlightAndExpectVisible( + page, + page.getByRole("button", { name: "Modal schließen" }) + ); +}); diff --git a/playwright/components/main/analogInputs/analogInputsTableTest.ts b/playwright/components/main/analogInputs/analogInputsTableTest.ts new file mode 100644 index 0000000..f291d24 --- /dev/null +++ b/playwright/components/main/analogInputs/analogInputsTableTest.ts @@ -0,0 +1,9 @@ +import { test } from "@playwright/test"; +import { highlightAndExpectVisible } from "@playwright/utils/highlight"; + +test("AnalogInputsTable renders rows", async ({ page }) => { + await page.goto("/analogInputs"); + await highlightAndExpectVisible(page, page.getByRole("table")); + // Mindestens eine Tabellenzeile sichtbar + await highlightAndExpectVisible(page, page.locator("tbody tr").first()); +}); diff --git a/playwright/components/main/analogInputs/analogInputsViewTest.ts b/playwright/components/main/analogInputs/analogInputsViewTest.ts new file mode 100644 index 0000000..b6da8f8 --- /dev/null +++ b/playwright/components/main/analogInputs/analogInputsViewTest.ts @@ -0,0 +1,12 @@ +import { test, expect } from "@playwright/test"; +import { highlightAndExpectVisible } from "@playwright/utils/highlight"; + +test("AnalogInputsView shows heading and table", async ({ page }) => { + await page.goto("/analogInputs"); + await highlightAndExpectVisible( + page, + page.getByRole("heading", { name: "Messwerteingänge" }) + ); + await highlightAndExpectVisible(page, page.getByRole("table")); + await expect(page.getByRole("table")).toBeVisible(); +}); diff --git a/playwright/components/main/analogInputs/xioPMTest.ts b/playwright/components/main/analogInputs/xioPMTest.ts new file mode 100644 index 0000000..319e555 --- /dev/null +++ b/playwright/components/main/analogInputs/xioPMTest.ts @@ -0,0 +1,5 @@ +import { test } from "@playwright/test"; + +test.fixme("XioPM visual presence", async ({ page }) => { + await page.goto("/analogInputs"); +}); diff --git a/playwright/pages/analogInputsTest.ts b/playwright/pages/analogInputsTest.ts new file mode 100644 index 0000000..73f5080 --- /dev/null +++ b/playwright/pages/analogInputsTest.ts @@ -0,0 +1,6 @@ +import { test } from "@playwright/test"; +import { runAnalogInputsTest } from "../tests/pages/analogInputs/analogInputsTest"; + +test("analog inputs page", async ({ page }) => { + await runAnalogInputsTest(page); +}); diff --git a/playwright/pages/dashboardTest.ts b/playwright/pages/dashboardTest.ts new file mode 100644 index 0000000..beda882 --- /dev/null +++ b/playwright/pages/dashboardTest.ts @@ -0,0 +1,6 @@ +import { test } from "@playwright/test"; +import { runDashboardTest } from "../tests/pages/dashboard/dashboardTest"; + +test("dashboard page", async ({ page }) => { + await runDashboardTest(page); +}); diff --git a/playwright/pages/digitalInputsTest.ts b/playwright/pages/digitalInputsTest.ts new file mode 100644 index 0000000..66441fc --- /dev/null +++ b/playwright/pages/digitalInputsTest.ts @@ -0,0 +1,6 @@ +import { test } from "@playwright/test"; +import { runDigitalInputsTest } from "../tests/pages/digitalInputs/digitalInputsTest"; + +test("digital inputs page", async ({ page }) => { + await runDigitalInputsTest(page); +}); diff --git a/playwright/pages/digitalOutputsTest.ts b/playwright/pages/digitalOutputsTest.ts new file mode 100644 index 0000000..cc74b90 --- /dev/null +++ b/playwright/pages/digitalOutputsTest.ts @@ -0,0 +1,6 @@ +import { test } from "@playwright/test"; +import { runDigitalOutputsTest } from "../tests/pages/digitalOutputs/digitalOutputsTest"; + +test("digital outputs page", async ({ page }) => { + await runDigitalOutputsTest(page); +}); diff --git a/playwright/pages/einstellungenTest.ts b/playwright/pages/einstellungenTest.ts new file mode 100644 index 0000000..1c4e3c1 --- /dev/null +++ b/playwright/pages/einstellungenTest.ts @@ -0,0 +1,6 @@ +import { test } from "@playwright/test"; +import { runSettingsPageTest } from "../tests/pages/settingsPage/settingsPageTest"; + +test("einstellungen page", async ({ page }) => { + await runSettingsPageTest(page); +}); diff --git a/playwright/pages/indexTest.ts b/playwright/pages/indexTest.ts new file mode 100644 index 0000000..ee882b0 --- /dev/null +++ b/playwright/pages/indexTest.ts @@ -0,0 +1,5 @@ +import { test } from "@playwright/test"; + +test("index page", async ({ page }) => { + await page.goto("/"); +}); diff --git a/playwright/pages/kabelueberwachungTest.ts b/playwright/pages/kabelueberwachungTest.ts new file mode 100644 index 0000000..9a98134 --- /dev/null +++ b/playwright/pages/kabelueberwachungTest.ts @@ -0,0 +1,6 @@ +import { test } from "@playwright/test"; +import { runCableMonitoringTest } from "../tests/pages/kabelueberwachung/kabelueberwachungTest"; + +test("kabelueberwachung page", async ({ page }) => { + await runCableMonitoringTest(page); +}); diff --git a/playwright/pages/meldungenTest.ts b/playwright/pages/meldungenTest.ts new file mode 100644 index 0000000..704068f --- /dev/null +++ b/playwright/pages/meldungenTest.ts @@ -0,0 +1,6 @@ +import { test } from "@playwright/test"; +import { runMeldungenTest } from "../tests/pages/meldungen/meldungenTest"; + +test("meldungen page", async ({ page }) => { + await runMeldungenTest(page); +}); diff --git a/playwright/pages/systemTest.ts b/playwright/pages/systemTest.ts new file mode 100644 index 0000000..9c0cedd --- /dev/null +++ b/playwright/pages/systemTest.ts @@ -0,0 +1,6 @@ +import { test } from "@playwright/test"; +import { runSystemTest } from "../tests/pages/system/systemTest"; + +test("system page", async ({ page }) => { + await runSystemTest(page); +}); diff --git a/playwright/pages/zutrittskontrolleTest.ts b/playwright/pages/zutrittskontrolleTest.ts new file mode 100644 index 0000000..40f0167 --- /dev/null +++ b/playwright/pages/zutrittskontrolleTest.ts @@ -0,0 +1,5 @@ +import { test } from "@playwright/test"; + +test("zutrittskontrolle page", async ({ page }) => { + await page.goto("/zutrittskontrolle"); +}); diff --git a/scripts/find-missing-playwright-tests.cjs b/scripts/find-missing-playwright-tests.cjs new file mode 100644 index 0000000..a04e88b --- /dev/null +++ b/scripts/find-missing-playwright-tests.cjs @@ -0,0 +1,84 @@ +#!/usr/bin/env node +/* + Scan TSX sources and report missing Playwright tests following the convention: + - For file: /(components|pages|...)/path/Foo.tsx + - Expect test at: playwright//path/fooTest.ts + (lowerCamel + 'Test.ts' or same baseName + 'Test.ts'). + + You can adjust the mapping rules below to your preference. +*/ +const fs = require("fs"); +const path = require("path"); + +const projectRoot = process.cwd(); +const srcRoots = ["components", "pages", "redux", "services"]; +const testsRoot = path.join(projectRoot, "playwright"); + +/** + * Map a TSX file to a desired Playwright test path. + * Current rule: + * //.tsx -> playwright///Test.ts + * where name = baseName with first letter lowercased. + */ +function mapToTest(tsxAbs) { + const rel = path.relative(projectRoot, tsxAbs).replace(/\\/g, "/"); + const parts = rel.split("/"); + const top = parts.shift(); + if (!srcRoots.includes(top)) return null; // ignore non-mapped roots + const file = parts.pop(); + if (!file) return null; + const base = file.replace(/\.tsx?$/, ""); + // lowerCamel for test file base name + const lowerCamel = base.charAt(0).toLowerCase() + base.slice(1); + const testRel = path + .join("playwright", top, ...parts, `${lowerCamel}Test.ts`) + .replace(/\\/g, "/"); + return path.join(projectRoot, testRel); +} + +function walk(dir, files = []) { + for (const entry of fs.readdirSync(dir, { withFileTypes: true })) { + if (entry.name.startsWith(".") || entry.name === "node_modules") continue; + const p = path.join(dir, entry.name); + if (entry.isDirectory()) walk(p, files); + else files.push(p); + } + return files; +} + +function main() { + const tsxFiles = []; + for (const root of srcRoots) { + const abs = path.join(projectRoot, root); + if (!fs.existsSync(abs)) continue; + tsxFiles.push(...walk(abs).filter((f) => /\.tsx$/.test(f))); + } + + const results = []; + for (const tsx of tsxFiles) { + const testPath = mapToTest(tsx); + if (!testPath) continue; + if (!fs.existsSync(testPath)) { + results.push({ tsx, testPath }); + } + } + + if (results.length === 0) { + console.log( + "✅ Alle TSX-Dateien haben entsprechende Playwright-Tests nach der Konvention." + ); + return; + } + + console.log("❌ Fehlende Playwright-Tests gefunden (Vorschlagspfade):"); + for (const r of results) { + const relSrc = path.relative(projectRoot, r.tsx).replace(/\\/g, "/"); + const relTest = path.relative(projectRoot, r.testPath).replace(/\\/g, "/"); + console.log(`- ${relSrc} -> ${relTest}`); + } + + // Exit non-zero to make it CI-enforceable + process.exitCode = 1; +} + +main(); diff --git a/scripts/find-missing-playwright-tests.mjs b/scripts/find-missing-playwright-tests.mjs new file mode 100644 index 0000000..f2b5d0e --- /dev/null +++ b/scripts/find-missing-playwright-tests.mjs @@ -0,0 +1,74 @@ +#!/usr/bin/env node +/* + Scan TSX sources and report missing Playwright tests following the convention: + - For file: /(components|pages|redux|services)/path/Foo.tsx + - Expect test at: playwright//path/fooTest.ts + + Adjust srcRoots to your needs. +*/ +import fs from "fs"; +import path from "path"; + +const projectRoot = process.cwd(); +const srcRoots = ["components", "pages", "redux", "services"]; + +function mapToTest(tsxAbs) { + const rel = path.relative(projectRoot, tsxAbs).replace(/\\/g, "/"); + const parts = rel.split("/"); + const top = parts.shift(); + if (!srcRoots.includes(top)) return null; + const file = parts.pop(); + if (!file) return null; + const base = file.replace(/\.tsx?$/, ""); + const lowerCamel = base.charAt(0).toLowerCase() + base.slice(1); + const testRel = path + .join("playwright", top, ...parts, `${lowerCamel}Test.ts`) + .replace(/\\/g, "/"); + return path.join(projectRoot, testRel); +} + +function walk(dir, files = []) { + for (const entry of fs.readdirSync(dir, { withFileTypes: true })) { + if (entry.name.startsWith(".") || entry.name === "node_modules") continue; + const p = path.join(dir, entry.name); + if (entry.isDirectory()) walk(p, files); + else files.push(p); + } + return files; +} + +function main() { + const tsxFiles = []; + for (const root of srcRoots) { + const abs = path.join(projectRoot, root); + if (!fs.existsSync(abs)) continue; + tsxFiles.push(...walk(abs).filter((f) => /\.tsx$/.test(f))); + } + + const results = []; + for (const tsx of tsxFiles) { + const testPath = mapToTest(tsx); + if (!testPath) continue; + if (!fs.existsSync(testPath)) { + results.push({ tsx, testPath }); + } + } + + if (results.length === 0) { + console.log( + "✅ Alle TSX-Dateien haben entsprechende Playwright-Tests nach der Konvention." + ); + return; + } + + console.log("❌ Fehlende Playwright-Tests gefunden (Vorschlagspfade):"); + for (const r of results) { + const relSrc = path.relative(projectRoot, r.tsx).replace(/\\/g, "/"); + const relTest = path.relative(projectRoot, r.testPath).replace(/\\/g, "/"); + console.log(`- ${relSrc} -> ${relTest}`); + } + + process.exitCode = 1; +} + +main();