diff --git a/.env.development b/.env.development index a9d0753bd..2b136f1a1 100644 --- a/.env.development +++ b/.env.development @@ -23,4 +23,4 @@ NEXT_PUBLIC_USE_MOCKS=true # z.B. http://10.10.0.13/xyz/index.aspx -> basePath in config.json auf /xyz setzen # basePath wird jetzt in public/config.json gepflegt # App-Versionsnummer -NEXT_PUBLIC_APP_VERSION=1.1.369 +NEXT_PUBLIC_APP_VERSION=1.1.370 diff --git a/.env.production b/.env.production index fe7890987..9db4c319d 100644 --- a/.env.production +++ b/.env.production @@ -24,4 +24,4 @@ NEXT_PUBLIC_USE_MOCKS=false # basePath wird jetzt in public/config.json gepflegt # App-Versionsnummer -NEXT_PUBLIC_APP_VERSION=1.1.369 +NEXT_PUBLIC_APP_VERSION=1.1.370 diff --git a/components/uiWidgets/baseMapPanel/BaseMapPanel.js b/components/uiWidgets/baseMapPanel/BaseMapPanel.js index ddffdbf72..91db9c669 100644 --- a/components/uiWidgets/baseMapPanel/BaseMapPanel.js +++ b/components/uiWidgets/baseMapPanel/BaseMapPanel.js @@ -1,4 +1,4 @@ -// components/uiWidgets/baseMapPanel/BaseMapPanel.js +// components/uiWidgets/baseMapPanel/BaseMapPanel.js , aus rechliche Grunde nur OSM, dieses Feature ist optional, aktuell nicht genutzt import React, { useEffect, useMemo, useRef, useState } from "react"; import L from "leaflet"; import { Icon } from "@iconify/react"; diff --git a/package-lock.json b/package-lock.json index d363c9e8f..ddd9b38ba 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "nodemap", - "version": "1.1.369", + "version": "1.1.370", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "nodemap", - "version": "1.1.369", + "version": "1.1.370", "dependencies": { "@emotion/react": "^11.13.3", "@emotion/styled": "^11.13.0", diff --git a/package.json b/package.json index 27e050949..1ef7ddb21 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "nodemap", - "version": "1.1.369", + "version": "1.1.370", "dependencies": { "@emotion/react": "^11.13.3", "@emotion/styled": "^11.13.0", diff --git a/playwright/tests/mapcomponent.spec.js b/playwright/tests/mapcomponent.spec.js index c1c59cc4c..a47a092d5 100644 --- a/playwright/tests/mapcomponent.spec.js +++ b/playwright/tests/mapcomponent.spec.js @@ -51,6 +51,114 @@ async function panMap(page, deltaY = -200) { ); } +/** + * Helper: Move mouse to the visual center of the #map element. + */ +async function moveMouseToMapCenter(page) { + const map = page.locator("#map"); + await map.waitFor({ state: "visible" }); + await page.locator("#map.leaflet-container").waitFor({ state: "visible", timeout: 20_000 }); + const box = await map.boundingBox(); + if (!box) throw new Error("Map bounding box not found"); + const cx = box.x + box.width / 2; + const cy = box.y + box.height / 2; + await page.mouse.move(cx, cy); + return { cx, cy }; +} + +/** + * Helper: Read map zoom from localStorage as a number. Returns NaN if not set. + */ +async function getZoomFromLocalStorage(page) { + return await page.evaluate(() => { + const v = localStorage.getItem("mapZoom"); + return v ? Number(v) : NaN; + }); +} + +/** + * Helper: Wait until mapZoom in localStorage changes compared to a previous value. + * Optionally enforce a direction via compareFn(newZoom, oldZoom) => boolean. + */ +async function waitForZoomChange(page, previousZoom, compareFn) { + await page.waitForFunction( + (prev, cmp) => { + const v = localStorage.getItem("mapZoom"); + if (!v) return false; + const z = Number(v); + if (Number.isNaN(z)) return false; + if (typeof cmp === "string" && cmp === "gt") return z > prev; + if (typeof cmp === "string" && cmp === "lt") return z < prev; + if (typeof cmp === "string" && cmp === "ne") return z !== prev; + return z !== prev; + }, + previousZoom, + { timeout: 10_000 } + ); +} + +/** + * Helper: Zoom the map using wheel input at map center. + * Uses page.mouse.wheel when available; otherwise dispatches a WheelEvent in the page context. + * Negative deltaY zooms in; positive deltaY zooms out. + */ +async function wheelZoom(page, deltaY = -400) { + const { cx, cy } = await moveMouseToMapCenter(page); + // Try native Playwright wheel first + try { + await page.mouse.wheel(0, deltaY); + return; + } catch { + // Fallback: dispatch a real WheelEvent at the map element + await page.evaluate( + ({ selector, deltaY, cx, cy }) => { + const el = document.querySelector(selector); + if (!el) return false; + const evt = new WheelEvent("wheel", { + deltaY, + clientX: cx, + clientY: cy, + bubbles: true, + cancelable: true, + view: window, + }); + el.dispatchEvent(evt); + return true; + }, + { selector: "#map", deltaY, cx, cy } + ); + } +} + +// Attach localStorage snapshot on failure to aid debugging +test.afterEach(async ({ page }, testInfo) => { + // Only capture on unexpected failure + if (testInfo.status !== testInfo.expectedStatus) { + const snapshot = await page.evaluate(() => { + const keys = [ + "mapZoom", + "mapCenter", + "showAppInfoCard", + "showCoordinateInput", + "showLayersPanel", + "showAreaDropdown", + "currentMapId", + "currentUserId", + ]; + const out = {}; + for (const k of keys) out[k] = localStorage.getItem(k); + return out; + }); + // Attach as artifact and also log for convenience + await testInfo.attach("localStorage.json", { + contentType: "application/json", + body: JSON.stringify(snapshot, null, 2), + }); + // eslint-disable-next-line no-console + console.log("[localStorage snapshot]", snapshot); + } +}); + test("MapComponent", async ({ page }) => { await page.goto("http://localhost:3000/?m=12&u=484"); // 10 Sekunden warten, bis die Karte sichtbar ist @@ -127,3 +235,36 @@ test("MapComponent", async ({ page }) => { await page.getByRole("combobox").selectOption("50977"); await page.getByRole("button", { name: "Karte auf Standardansicht" }).click(); }); + +test("mouse wheel zoom updates mapZoom", async ({ page }) => { + // Set initial state before navigation so the app can read them on load + await page.addInitScript(() => { + localStorage.setItem("currentMapId", "12"); + localStorage.setItem("currentUserId", "484"); + localStorage.setItem("mapCenter", JSON.stringify([53.23938294961826, 8.21434020996094])); + localStorage.setItem("mapZoom", "10"); + localStorage.setItem("showAppInfoCard", "false"); + localStorage.setItem("showCoordinateInput", "false"); + localStorage.setItem("showLayersPanel", "false"); + localStorage.setItem("showAreaDropdown", "false"); + }); + + await page.goto("http://localhost:3000/?m=12&u=484"); + + await page.locator("#map.leaflet-container").waitFor({ state: "visible", timeout: 20_000 }); + + const before = await getZoomFromLocalStorage(page); + expect(Number.isNaN(before)).toBeFalsy(); + + // Zoom in via wheel and expect zoom to increase + await wheelZoom(page, -600); + await waitForZoomChange(page, before, "gt"); + const afterIn = await getZoomFromLocalStorage(page); + expect(afterIn).toBeGreaterThan(before); + + // Zoom out via wheel and expect zoom to decrease + await wheelZoom(page, 800); + await waitForZoomChange(page, afterIn, "lt"); + const afterOut = await getZoomFromLocalStorage(page); + expect(afterOut).toBeLessThan(afterIn); +}); diff --git a/reports/junit/playwright.xml b/reports/junit/playwright.xml index 35722d447..63a3cbeff 100644 --- a/reports/junit/playwright.xml +++ b/reports/junit/playwright.xml @@ -1,9 +1,75 @@ - - - + + + + + + Timeout: 10000ms + + Call log: + - Expect "toBeVisible" with timeout 10000ms + - waiting for getByRole('button', { name: 'Info ausblenden' }) + + + 210 | ).toBeVisible(); + 211 | await page.getByRole("button", { name: "Layer-Panel ausblenden" }).click(); + > 212 | await expect(page.getByRole("button", { name: "Info ausblenden" })).toBeVisible(); + | ^ + 213 | await page.getByRole("button", { name: "Info ausblenden" }).click(); + 214 | await page.getByRole("button", { name: "Info einblenden" }).click(); + 215 | await expect(page.locator("div").filter({ hasText: "TALAS.Map Version" }).nth(3)).toBeVisible(); + at C:\Users\isa.LTW\Desktop\15.09.2025\NodeMap\15.09.2025 NodeMap V1.1.350\playwright\tests\mapcomponent.spec.js:212:71 + + attachment #1: screenshot (image/png) ────────────────────────────────────────────────────────── + ..\..\test-results\mapcomponent-MapComponent-chromium\test-failed-1.png + ──────────────────────────────────────────────────────────────────────────────────────────────── + + attachment #3: video (video/webm) ────────────────────────────────────────────────────────────── + ..\..\test-results\mapcomponent-MapComponent-chromium\video.webm + ──────────────────────────────────────────────────────────────────────────────────────────────── + + Error Context: ..\..\test-results\mapcomponent-MapComponent-chromium\error-context.md + + attachment #5: trace (application/zip) ───────────────────────────────────────────────────────── + ..\..\test-results\mapcomponent-MapComponent-chromium\trace.zip + Usage: + + npx playwright show-trace ..\..\test-results\mapcomponent-MapComponent-chromium\trace.zip + + ──────────────────────────────────────────────────────────────────────────────────────────────── +]]> + + + + + + diff --git a/test-results/mapcomponent-MapComponent-chromium/error-context.md b/test-results/mapcomponent-MapComponent-chromium/error-context.md new file mode 100644 index 000000000..d3e387439 --- /dev/null +++ b/test-results/mapcomponent-MapComponent-chromium/error-context.md @@ -0,0 +1,59 @@ +# Page snapshot + +```yaml +- generic [ref=e1]: + - generic [ref=e3]: + - generic [ref=e4]: + - generic: + - generic: + - button "Marker" [ref=e5] [cursor=pointer] + - button "Marker" [ref=e6] [cursor=pointer] + - button "Marker" [ref=e7] [cursor=pointer] + - button "Marker" [ref=e8] [cursor=pointer] + - button "Marker" [ref=e9] [cursor=pointer] + - button "Marker" [ref=e10] [cursor=pointer] + - button "Marker" [ref=e11] [cursor=pointer] + - button "Marker" [ref=e12] [cursor=pointer] + - button "Marker" [ref=e13] [cursor=pointer] + - button "Marker" [ref=e14] [cursor=pointer] + - button "Marker" [ref=e15] [cursor=pointer] + - button "Marker" [ref=e16] [cursor=pointer] + - button "Marker" [ref=e17] [cursor=pointer] + - button "Marker" [ref=e18] [cursor=pointer] + - button "Marker" [ref=e19] [cursor=pointer] + - button "Marker" [ref=e20] [cursor=pointer] + - button "Marker" [ref=e21] [cursor=pointer] + - button "Marker" [ref=e22] [cursor=pointer] + - button "Marker" [ref=e23] [cursor=pointer] + - button "Marker" [ref=e24] [cursor=pointer] + - button "Marker" [ref=e25] [cursor=pointer] + - button "Marker" [ref=e26] [cursor=pointer] + - button "Marker" [ref=e27] [cursor=pointer] + - button "Marker" [ref=e28] [cursor=pointer] + - button "Marker" [ref=e29] [cursor=pointer] + - button "Marker" [ref=e30] [cursor=pointer] + - button "Marker" [ref=e31] [cursor=pointer] + - button "Marker" [ref=e32] [cursor=pointer] + - button "Marker" [ref=e33] [cursor=pointer] + - generic [ref=e34]: + - link "Leaflet" [ref=e35] [cursor=pointer]: + - /url: https://leafletjs.com + - img [ref=e36] [cursor=pointer] + - text: Leaflet + - generic [ref=e40]: "|" + - text: © OpenStreetMap contributors + - generic [ref=e41]: + - button "Marker" [ref=e42] [cursor=pointer]: + - img [ref=e43] [cursor=pointer] + - button "Koordinatensuche einblenden" [ref=e46] [cursor=pointer]: + - img [ref=e47] [cursor=pointer] + - button "Bearbeitungsmodus aktivieren" [ref=e49] [cursor=pointer]: + - img [ref=e50] [cursor=pointer] + - button "Karte auf Standardansicht" [ref=e52] [cursor=pointer]: + - img [ref=e53] [cursor=pointer] + - button "Layer-Panel einblenden" [active] [ref=e55] [cursor=pointer]: + - img [ref=e56] [cursor=pointer] + - button "Info einblenden" [ref=e58] [cursor=pointer]: + - img [ref=e59] [cursor=pointer] + - alert [ref=e61] +``` \ No newline at end of file diff --git a/test-results/mapcomponent-MapComponent-chromium/test-failed-1.png b/test-results/mapcomponent-MapComponent-chromium/test-failed-1.png new file mode 100644 index 000000000..637192072 Binary files /dev/null and b/test-results/mapcomponent-MapComponent-chromium/test-failed-1.png differ diff --git a/test-results/mapcomponent-MapComponent-chromium/trace.zip b/test-results/mapcomponent-MapComponent-chromium/trace.zip index 5f0574405..7720a2dfe 100644 Binary files a/test-results/mapcomponent-MapComponent-chromium/trace.zip and b/test-results/mapcomponent-MapComponent-chromium/trace.zip differ diff --git a/test-results/mapcomponent-MapComponent-chromium/video.webm b/test-results/mapcomponent-MapComponent-chromium/video.webm new file mode 100644 index 000000000..3e85aae87 Binary files /dev/null and b/test-results/mapcomponent-MapComponent-chromium/video.webm differ diff --git a/test-results/mapcomponent-UI-respects-localStorage-on-load-chromium/trace.zip b/test-results/mapcomponent-UI-respects-localStorage-on-load-chromium/trace.zip deleted file mode 100644 index 2a9e74128..000000000 Binary files a/test-results/mapcomponent-UI-respects-localStorage-on-load-chromium/trace.zip and /dev/null differ diff --git a/test-results/mapcomponent-map-can-be-panned-by-drag-chromium/trace.zip b/test-results/mapcomponent-map-can-be-panned-by-drag-chromium/trace.zip deleted file mode 100644 index 1710e92de..000000000 Binary files a/test-results/mapcomponent-map-can-be-panned-by-drag-chromium/trace.zip and /dev/null differ diff --git a/test-results/mapcomponent-localStorage-updates-when-toggling-UI-controls-chromium/trace.zip b/test-results/mapcomponent-mouse-wheel-zoom-updates-mapZoom-chromium/trace.zip similarity index 50% rename from test-results/mapcomponent-localStorage-updates-when-toggling-UI-controls-chromium/trace.zip rename to test-results/mapcomponent-mouse-wheel-zoom-updates-mapZoom-chromium/trace.zip index 16336c005..e71a798f2 100644 Binary files a/test-results/mapcomponent-localStorage-updates-when-toggling-UI-controls-chromium/trace.zip and b/test-results/mapcomponent-mouse-wheel-zoom-updates-mapZoom-chromium/trace.zip differ diff --git a/test-results/mapcomponent-test-chromium/trace.zip b/test-results/mapcomponent-test-chromium/trace.zip deleted file mode 100644 index d03440857..000000000 Binary files a/test-results/mapcomponent-test-chromium/trace.zip and /dev/null differ