feat(ui): refine governed workbench and dual-screen flows

This commit is contained in:
Jens
2026-08-30 06:00:28 +02:00
parent 80a2d1654d
commit a0884d64c9
48 changed files with 1360 additions and 184 deletions
+51 -1
View File
@@ -94,6 +94,9 @@ async function layoutEvidence(page) {
const main = document.querySelector('.workbench-main')?.getBoundingClientRect()
const map = document.querySelector('.geo-map-stage')?.getBoundingClientRect()
const theme = document.querySelector('.geo-theme-panel')?.getBoundingClientRect()
const themeList = document.querySelector('.geo-theme-list')?.getBoundingClientRect()
const firstTheme = document.querySelector('.geo-theme-option')?.getBoundingClientRect()
const sourceSummary = document.querySelector('.geo-source-summary')?.getBoundingClientRect()
return {
viewport_width: window.innerWidth,
viewport_height: window.innerHeight,
@@ -108,6 +111,9 @@ async function layoutEvidence(page) {
main: main ? { left: main.left, right: main.right, width: main.width } : null,
map: map ? { left: map.left, right: map.right, width: map.width, height: map.height } : null,
theme: theme ? { left: theme.left, right: theme.right, width: theme.width } : null,
theme_list: themeList ? { top: themeList.top, bottom: themeList.bottom, height: themeList.height } : null,
first_theme: firstTheme ? { top: firstTheme.top, bottom: firstTheme.bottom, height: firstTheme.height } : null,
source_summary: sourceSummary ? { top: sourceSummary.top, bottom: sourceSummary.bottom, height: sourceSummary.height } : null,
}
})
}
@@ -177,12 +183,21 @@ async function runViewport(browser, baseUrl, outputDir, viewport) {
}
})
try {
await prepareAuditSession(page, baseUrl)
const auditSession = await prepareAuditSession(page, baseUrl)
const startedAt = Date.now()
await page.goto(baseUrl, { waitUntil: 'networkidle', timeout: 60_000 })
await page.getByTestId('map-workspace').waitFor({ state: 'visible', timeout: 30_000 })
const readyMs = Date.now() - startedAt
await auditInteractiveNames(page, `${viewport.width}px map explorer`)
if (auditSession?.role === 'guest') {
const exposedAcquisitionActions = await page.locator('.geo-theme-option').evaluateAll((buttons) => buttons
.filter((button) => button.textContent?.includes('Op aanvraag') && !button.disabled)
.map((button) => button.textContent?.trim() || ''))
assert(
exposedAcquisitionActions.length > 0,
'Guest UI must expose bounded official source acquisition inside the signed demo project',
)
}
const layout = await layoutEvidence(page)
const clippedNavigationLabels = await page.locator('.nav-item span').evaluateAll((labels) => labels
.filter((label) => label.getClientRects().length > 0 && label.scrollWidth > label.clientWidth + 1)
@@ -190,6 +205,16 @@ async function runViewport(browser, baseUrl, outputDir, viewport) {
assert.equal(layout.horizontal_overflow_px, 0, `${viewport.width}px layout overflows horizontally`)
assert.deepEqual(clippedNavigationLabels, [], `${viewport.width}px navigation clips visible labels`)
assert(layout.map && layout.map.width >= Math.min(320, viewport.width - 32), `${viewport.width}px map is too narrow`)
if (viewport.width === 1366 && layout.theme && layout.theme_list && layout.first_theme) {
assert(
layout.theme_list.height >= layout.first_theme.height,
'1366px theme list is shorter than one selectable theme row',
)
assert(
!layout.source_summary || layout.source_summary.bottom <= layout.theme.bottom + 1,
'1366px source summary falls outside the theme column',
)
}
if (layout.topbar && layout.guest_banner) {
assert(
layout.topbar.bottom <= layout.guest_banner.top + 1,
@@ -222,6 +247,31 @@ async function runViewport(browser, baseUrl, outputDir, viewport) {
await evolutionTab.press('ArrowLeft')
assert.equal(await currentTab.getAttribute('aria-selected'), 'true')
const coordinateSelection = page.locator('.geo-coordinate-selection')
await coordinateSelection.locator('summary').focus()
await coordinateSelection.locator('summary').press('Enter')
assert.equal(await coordinateSelection.getAttribute('open'), '')
await coordinateSelection.locator('summary').press('Enter')
const insightsToggle = page.getByRole('button', { name: 'Open inzichten' })
await insightsToggle.click()
const openDrawer = await page.locator('#geo-explorer-results').evaluate((element) => {
const bounds = element.getBoundingClientRect()
return { left: bounds.left, right: bounds.right, width: bounds.width, expanded: element.getAttribute('aria-hidden') }
})
assert(openDrawer.left < viewport.width - 100, 'Explicitly opened insights drawer remains off-screen')
assert(openDrawer.right <= viewport.width + 1, 'Explicitly opened insights drawer exceeds the viewport')
assert.equal(openDrawer.expanded, 'false')
await page.getByRole('button', { name: 'Sluit inzichten' }).click()
const themeToggle = page.locator('.workbench-theme-toggle')
await themeToggle.click()
const mapControlIcon = page.locator('.maplibregl-ctrl-icon').first()
if (await mapControlIcon.count()) {
assert.equal(await mapControlIcon.evaluate((element) => getComputedStyle(element).filter), 'none')
}
await themeToggle.click()
await page.screenshot({
path: path.join(outputDir, `viewport-${viewport.width}x${viewport.height}.png`),
fullPage: viewport.width <= 480,