Compare commits
10 Commits
8a9cd72718
...
c03802e97f
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c03802e97f | ||
|
|
1485c0c92c | ||
|
|
44ecbfa417 | ||
|
|
927a807c4d | ||
|
|
29a79ce0a9 | ||
|
|
2166744c63 | ||
|
|
81239f41ae | ||
|
|
584593ba71 | ||
|
|
4b83ff01cf | ||
|
|
8c88aa843c |
@@ -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.845
|
||||
NEXT_PUBLIC_APP_VERSION=1.6.855
|
||||
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.845
|
||||
NEXT_PUBLIC_APP_VERSION=1.6.855
|
||||
NEXT_PUBLIC_CPL_MODE=production
|
||||
@@ -15,6 +15,7 @@ steps:
|
||||
commands:
|
||||
- pwd
|
||||
- node -v && npm -v
|
||||
# Skip lifecycle scripts in CI to avoid running husky's prepare step
|
||||
- npm ci
|
||||
# Zeig mir, ob die Datei wirklich im Checkout liegt:
|
||||
- echo "=== git ls-files ==="
|
||||
@@ -33,20 +34,22 @@ steps:
|
||||
PORT: "3000"
|
||||
commands:
|
||||
- node -v && npm -v
|
||||
- npm ci
|
||||
# Skip lifecycle scripts in CI to avoid running husky's prepare step (husky is a devDep)
|
||||
- env npm_config_production=false npm ci
|
||||
- npm run build
|
||||
# Start local static simulator in background
|
||||
- node scripts/local-cpl-sim.mjs &
|
||||
- npm run server:sim &
|
||||
# Wait until simulator responds on port 3000 (no curl dependency)
|
||||
- |
|
||||
node -e "const http=require('http');let n=120;function ping(){http.get('http://localhost:3000',res=>{console.log('Server is up');process.exit(0)}).on('error',()=>{if(n--<=0){console.error('Server did not start');process.exit(1)}setTimeout(ping,1000)});}ping();"
|
||||
- node -e "const http=require('http');let n=120;function ping(){http.get('http://localhost:3000',res=>{console.log('Server is up');process.exit(0)}).on('error',()=>{if(n--<=0){console.error('Server did not start');process.exit(1)}setTimeout(ping,1000)});}ping();"
|
||||
- npx playwright test --project=chromium
|
||||
|
||||
- name: notify-success
|
||||
image: alpine/curl:latest
|
||||
when:
|
||||
status: success
|
||||
commands:
|
||||
- curl -d "Tests erfolgreich in woodpecker" https://ntfy.sh/OEOr8DNB0aT2mXWg231PeEEKwvuzt86qgM8ezQmgfcX9ZIlZ35
|
||||
|
||||
- name: notify-failure
|
||||
image: alpine/curl:latest
|
||||
when:
|
||||
|
||||
55
CHANGELOG.md
55
CHANGELOG.md
@@ -1,3 +1,58 @@
|
||||
## [1.6.855] – 2025-09-05
|
||||
|
||||
- fix: allow scripts in woodpecker
|
||||
|
||||
---
|
||||
## [1.6.854] – 2025-09-05
|
||||
|
||||
- fix: woodpecker allow scripts
|
||||
|
||||
---
|
||||
## [1.6.853] – 2025-09-05
|
||||
|
||||
- fix: woodpecker npm run server:sim
|
||||
|
||||
---
|
||||
## [1.6.852] – 2025-09-05
|
||||
|
||||
- fix: woodpecker
|
||||
|
||||
---
|
||||
## [1.6.851] – 2025-09-05
|
||||
|
||||
- fix: woodpecker rimraf not found
|
||||
|
||||
---
|
||||
## [1.6.850] – 2025-09-05
|
||||
|
||||
- fix: woodpecker compiler error
|
||||
|
||||
---
|
||||
## [1.6.849] – 2025-09-05
|
||||
|
||||
- fix: .woodpecker.yml
|
||||
|
||||
---
|
||||
## [1.6.848] – 2025-09-05
|
||||
|
||||
- test: playwright mit npm run dev erfolgreich
|
||||
|
||||
---
|
||||
## [1.6.847] – 2025-09-05
|
||||
|
||||
- chore: move playwright components folder to tests
|
||||
|
||||
---
|
||||
## [1.6.846] – 2025-09-05
|
||||
|
||||
- feat(kue705FO): scrolling für lange Modulnamen (48 Zeichen) + Version-Gate/Env-Override
|
||||
|
||||
- Unterstützt bis zu 48 Zeichen im Modulnamen; bei Überlänge automatische Laufschrift
|
||||
- Marquee via react-fast-marquee (SSR-sicher per next/dynamic)
|
||||
- Overflow-Erkennung + Tooltip mit vollem Namen
|
||||
- Version-Gate: aktiviert ab V4.30
|
||||
|
||||
---
|
||||
## [1.6.845] – 2025-09-05
|
||||
|
||||
- feat: prepare KÜ 8 for scrolling text
|
||||
|
||||
50
Jenkinsfile
vendored
50
Jenkinsfile
vendored
@@ -6,13 +6,51 @@ pipeline {
|
||||
stage('Versions') {
|
||||
steps { sh 'node -v && npm -v' }
|
||||
}
|
||||
stage('Install deps') {
|
||||
steps { sh 'npm ci' }
|
||||
}
|
||||
stage('Playwright tests') {
|
||||
|
||||
stage('Verify mocks') {
|
||||
steps {
|
||||
sh 'npx playwright install' // Browser-Binärdateien laden
|
||||
sh 'npx playwright test'
|
||||
sh '''
|
||||
set -euxo pipefail
|
||||
npm ci
|
||||
echo "=== git ls-files ==="
|
||||
git ls-files | grep -i "^mocks/device-cgi-simulator/SERVICE/systemMockData.js" || true
|
||||
echo "=== ls -la ==="
|
||||
ls -la mocks/device-cgi-simulator/SERVICE || true
|
||||
echo "=== file exists? ==="
|
||||
test -f mocks/device-cgi-simulator/SERVICE/systemMockData.js && echo "FOUND" || (echo "MISSING" && exit 1)
|
||||
'''
|
||||
}
|
||||
}
|
||||
|
||||
stage('Build & E2E (chromium)') {
|
||||
environment {
|
||||
CI = 'true'
|
||||
NODE_ENV = 'production'
|
||||
NEXT_TELEMETRY_DISABLED = '1'
|
||||
PORT = '3000'
|
||||
}
|
||||
steps {
|
||||
sh '''
|
||||
set -euxo pipefail
|
||||
# Install devDependencies as well (rimraf, cross-env, etc.)
|
||||
env npm_config_production=false npm ci
|
||||
|
||||
# Build Next.js
|
||||
npm run build
|
||||
|
||||
# Start local static simulator in background
|
||||
npm run server:sim &
|
||||
|
||||
# Ensure Playwright browsers and OS deps are installed (best-effort)
|
||||
npx playwright install-deps || true
|
||||
npx playwright install
|
||||
|
||||
# Wait until simulator responds on port 3000 (no curl dependency)
|
||||
node -e "const http=require('http');let n=120;function ping(){http.get('http://localhost:3000',res=>{console.log('Server is up');process.exit(0)}).on('error',()=>{if(n--<=0){console.error('Server did not start');process.exit(1)}setTimeout(ping,1000)});}ping();"
|
||||
|
||||
# Run tests (chromium only to match Woodpecker)
|
||||
npx playwright test --project=chromium
|
||||
'''
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "cpl-v4",
|
||||
"version": "1.6.845",
|
||||
"version": "1.6.855",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "cpl-v4",
|
||||
"version": "1.6.845",
|
||||
"version": "1.6.855",
|
||||
"dependencies": {
|
||||
"@fontsource/roboto": "^5.1.0",
|
||||
"@headlessui/react": "^2.2.4",
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
{
|
||||
"name": "cpl-v4",
|
||||
"version": "1.6.845",
|
||||
"version": "1.6.855",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev -p 3000",
|
||||
"clean": "rimraf .next out",
|
||||
"build": "npm run clean && cross-env EXPORT_STATIC=true next build",
|
||||
"postbuild": "node -e \"const fs=require('fs');const path=require('path');fs.mkdirSync('out',{recursive:true});fs.copyFileSync('LICENSE_ICONIFY.txt', path.join('out','LICENSE_ICONIFY.txt'))\"",
|
||||
"serve:sim": "node ./scripts/local-cpl-sim.mjs",
|
||||
"server:sim": "node ./scripts/local-cpl-sim.mjs",
|
||||
"start": "next start",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"check": "npm run lint && npm run typecheck",
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
import { test } from "@playwright/test";
|
||||
import { runAnalogInputsTest } from "../tests/pages/analogInputs/analogInputsTest";
|
||||
|
||||
test("analog inputs page", async ({ page }) => {
|
||||
await runAnalogInputsTest(page);
|
||||
});
|
||||
@@ -1,6 +0,0 @@
|
||||
import { test } from "@playwright/test";
|
||||
import { runDashboardTest } from "../tests/pages/dashboard/dashboardTest";
|
||||
|
||||
test("dashboard page", async ({ page }) => {
|
||||
await runDashboardTest(page);
|
||||
});
|
||||
@@ -1,6 +0,0 @@
|
||||
import { test } from "@playwright/test";
|
||||
import { runDigitalInputsTest } from "../tests/pages/digitalInputs/digitalInputsTest";
|
||||
|
||||
test("digital inputs page", async ({ page }) => {
|
||||
await runDigitalInputsTest(page);
|
||||
});
|
||||
@@ -1,6 +0,0 @@
|
||||
import { test } from "@playwright/test";
|
||||
import { runDigitalOutputsTest } from "../tests/pages/digitalOutputs/digitalOutputsTest";
|
||||
|
||||
test("digital outputs page", async ({ page }) => {
|
||||
await runDigitalOutputsTest(page);
|
||||
});
|
||||
@@ -1,6 +0,0 @@
|
||||
import { test } from "@playwright/test";
|
||||
import { runSettingsPageTest } from "../tests/pages/settingsPage/settingsPageTest";
|
||||
|
||||
test("einstellungen page", async ({ page }) => {
|
||||
await runSettingsPageTest(page);
|
||||
});
|
||||
@@ -1,5 +0,0 @@
|
||||
import { test } from "@playwright/test";
|
||||
|
||||
test("index page", async ({ page }) => {
|
||||
await page.goto("/");
|
||||
});
|
||||
@@ -1,6 +0,0 @@
|
||||
import { test } from "@playwright/test";
|
||||
import { runCableMonitoringTest } from "../tests/pages/kabelueberwachung/kabelueberwachungTest";
|
||||
|
||||
test("kabelueberwachung page", async ({ page }) => {
|
||||
await runCableMonitoringTest(page);
|
||||
});
|
||||
@@ -1,6 +0,0 @@
|
||||
import { test } from "@playwright/test";
|
||||
import { runMeldungenTest } from "../tests/pages/meldungen/meldungenTest";
|
||||
|
||||
test("meldungen page", async ({ page }) => {
|
||||
await runMeldungenTest(page);
|
||||
});
|
||||
@@ -1,6 +0,0 @@
|
||||
import { test } from "@playwright/test";
|
||||
import { runSystemTest } from "../tests/pages/system/systemTest";
|
||||
|
||||
test("system page", async ({ page }) => {
|
||||
await runSystemTest(page);
|
||||
});
|
||||
@@ -1,5 +0,0 @@
|
||||
import { test } from "@playwright/test";
|
||||
|
||||
test("zutrittskontrolle page", async ({ page }) => {
|
||||
await page.goto("/zutrittskontrolle");
|
||||
});
|
||||
@@ -1,9 +1,9 @@
|
||||
import type { Page } from "@playwright/test";
|
||||
import { expect } from "@playwright/test";
|
||||
import { highlightAndExpectVisible } from "@playwright/utils/highlight";
|
||||
import { navTest } from "@/playwright/components/navigation/navTest";
|
||||
import { headerTest } from "@/playwright/components/header/headerTest";
|
||||
import { footerTest } from "@/playwright/components/footer/footerTest";
|
||||
import { navTest } from "@/playwright/tests/components/navigation/navTest";
|
||||
import { headerTest } from "@/playwright/tests/components/header/headerTest";
|
||||
import { footerTest } from "@/playwright/tests/components/footer/footerTest";
|
||||
|
||||
// Kombinierte Helper-Funktion: injiziert CSS (nur einmal), hebt hervor und prüft Sichtbarkeit
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import type { Page } from "@playwright/test";
|
||||
import { highlightAndExpectVisible } from "@playwright/utils/highlight";
|
||||
import { navTest } from "@/playwright/components/navigation/navTest";
|
||||
import { headerTest } from "@/playwright/components/header/headerTest";
|
||||
import { footerTest } from "@/playwright/components/footer/footerTest";
|
||||
import { navTest } from "@/playwright/tests/components/navigation/navTest";
|
||||
import { headerTest } from "@/playwright/tests/components/header/headerTest";
|
||||
import { footerTest } from "@/playwright/tests/components/footer/footerTest";
|
||||
|
||||
export async function runDashboardTest(page: Page) {
|
||||
await page.goto("/dashboard");
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import type { Page } from "@playwright/test";
|
||||
import { highlightAndExpectVisible } from "@playwright/utils/highlight";
|
||||
import { navTest } from "@/playwright/components/navigation/navTest";
|
||||
import { headerTest } from "@/playwright/components/header/headerTest";
|
||||
import { footerTest } from "@/playwright/components/footer/footerTest";
|
||||
import { navTest } from "@/playwright/tests/components/navigation/navTest";
|
||||
import { headerTest } from "@/playwright/tests/components/header/headerTest";
|
||||
import { footerTest } from "@/playwright/tests/components/footer/footerTest";
|
||||
|
||||
export async function runDigitalInputsTest(page: Page) {
|
||||
await page.goto("/digitalInputs");
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import type { Page } from "@playwright/test";
|
||||
import { highlightAndExpectVisible } from "@playwright/utils/highlight";
|
||||
import { navTest } from "@/playwright/components/navigation/navTest";
|
||||
import { headerTest } from "@/playwright/components/header/headerTest";
|
||||
import { footerTest } from "@/playwright/components/footer/footerTest";
|
||||
import { navTest } from "@/playwright/tests/components/navigation/navTest";
|
||||
import { headerTest } from "@/playwright/tests/components/header/headerTest";
|
||||
import { footerTest } from "@/playwright/tests/components/footer/footerTest";
|
||||
|
||||
export async function runDigitalOutputsTest(page: Page) {
|
||||
await page.goto("/digitalOutputs");
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import type { Page } from "@playwright/test";
|
||||
import { highlightAndExpectVisible } from "@playwright/utils/highlight";
|
||||
import { navTest } from "@/playwright/components/navigation/navTest";
|
||||
import { headerTest } from "@/playwright/components/header/headerTest";
|
||||
import { footerTest } from "@/playwright/components/footer/footerTest";
|
||||
import { navTest } from "@/playwright/tests/components/navigation/navTest";
|
||||
import { headerTest } from "@/playwright/tests/components/header/headerTest";
|
||||
import { footerTest } from "@/playwright/tests/components/footer/footerTest";
|
||||
|
||||
export async function runCableMonitoringTest(page: Page) {
|
||||
await page.goto("/kabelueberwachung");
|
||||
@@ -94,7 +94,9 @@ export async function runCableMonitoringTest(page: Page) {
|
||||
);
|
||||
await page.waitForTimeout(400);
|
||||
|
||||
await highlightAndExpectVisible(page, page.getByText("Kabel 1"));
|
||||
// Use a unique locator to avoid strict mode violation (two elements contain text "Kabel 1").
|
||||
// The card exposes a title attribute "Kabel 1", so prefer getByTitle for a single match.
|
||||
await highlightAndExpectVisible(page, page.getByTitle("Kabel 1").first());
|
||||
await page.waitForTimeout(400);
|
||||
|
||||
await highlightAndExpectVisible(
|
||||
@@ -197,7 +199,11 @@ export async function runCableMonitoringTest(page: Page) {
|
||||
);
|
||||
await page.waitForTimeout(400);
|
||||
|
||||
await highlightAndExpectVisible(page, page.getByText("Kabel 8"));
|
||||
// For cable 8 the UI shows a long name and exposes it via title attribute; target it explicitly
|
||||
await highlightAndExpectVisible(
|
||||
page,
|
||||
page.getByTitle("Kabel_8 in Salzgitter bei Hannover").first()
|
||||
);
|
||||
await page.waitForTimeout(400);
|
||||
|
||||
await page.waitForTimeout(400);
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import type { Page } from "@playwright/test";
|
||||
import { highlightAndExpectVisible } from "@playwright/utils/highlight";
|
||||
import { navTest } from "@/playwright/components/navigation/navTest";
|
||||
import { headerTest } from "@/playwright/components/header/headerTest";
|
||||
import { footerTest } from "@/playwright/components/footer/footerTest";
|
||||
import { navTest } from "@/playwright/tests/components/navigation/navTest";
|
||||
import { headerTest } from "@/playwright/tests/components/header/headerTest";
|
||||
import { footerTest } from "@/playwright/tests/components/footer/footerTest";
|
||||
|
||||
export async function runMeldungenTest(page: Page) {
|
||||
await page.goto("/meldungen");
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import type { Page } from "@playwright/test";
|
||||
import { highlightAndExpectVisible } from "@playwright/utils/highlight";
|
||||
import { navTest } from "@/playwright/components/navigation/navTest";
|
||||
import { headerTest } from "@/playwright/components/header/headerTest";
|
||||
import { footerTest } from "@/playwright/components/footer/footerTest";
|
||||
import { navTest } from "@/playwright/tests/components/navigation/navTest";
|
||||
import { headerTest } from "@/playwright/tests/components/header/headerTest";
|
||||
import { footerTest } from "@/playwright/tests/components/footer/footerTest";
|
||||
|
||||
export async function runSettingsPageTest(page: Page) {
|
||||
await page.goto("/einstellungen");
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import type { Page } from "@playwright/test";
|
||||
import { highlightAndExpectVisible } from "@playwright/utils/highlight";
|
||||
import { navTest } from "@/playwright/components/navigation/navTest";
|
||||
import { headerTest } from "@/playwright/components/header/headerTest";
|
||||
import { footerTest } from "@/playwright/components/footer/footerTest";
|
||||
import { navTest } from "@/playwright/tests/components/navigation/navTest";
|
||||
import { headerTest } from "@/playwright/tests/components/header/headerTest";
|
||||
import { footerTest } from "@/playwright/tests/components/footer/footerTest";
|
||||
|
||||
export async function runSystemTest(page: Page) {
|
||||
await page.goto("/system");
|
||||
|
||||
@@ -55,5 +55,10 @@
|
||||
"types/global.d.ts"
|
||||
],
|
||||
|
||||
"exclude": ["node_modules", ".next", "out"]
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
".next",
|
||||
"out",
|
||||
"public"
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user