const { test, expect } = require('@playwright/test'); async function waitForVehicleMarkers(page) { await page.waitForSelector('.leaflet-marker-icon', { state: 'attached' }); await expect.poll(async () => page.locator('.leaflet-marker-icon').count(), { timeout: 10000 }).toBeGreaterThan(0); } test.describe('kort7 vehicle map', () => { test('loads map and renders vehicles', async ({ page }) => { await page.goto('/kort7.html'); await expect(page.locator('#map')).toBeVisible(); await waitForVehicleMarkers(page); await expect(page.locator('#status')).toContainText('Simuleret tid'); }); test('shows vehicle popup with details when clicking a marker', async ({ page }) => { await page.goto('/kort7.html'); await waitForVehicleMarkers(page); await page.getByRole('button', { name: 'Pause' }).click(); const firstMarker = page.locator('.leaflet-marker-icon').first(); await firstMarker.click({ force: true }); const popup = page.locator('.leaflet-popup'); await expect(popup).toBeVisible(); await expect(popup).toContainText(/Bil \d/); await expect(popup).toContainText('Tid:'); await expect(popup).toContainText('Lat:'); await expect(popup).toContainText('Lon:'); await expect(popup).toContainText('Hastighed:'); await expect(popup).toContainText('Retning:'); await expect(popup).toContainText('Usikkerhed:'); await expect(popup).toContainText('På kortet:'); }); test('renders uncertainty circles for vehicles with uncertainty', async ({ page }) => { await page.goto('/kort7.html'); await waitForVehicleMarkers(page); await expect.poll(async () => { return await page.locator('path').evaluateAll((nodes) => nodes.filter((node) => { const strokeDasharray = node.getAttribute('stroke-dasharray'); return strokeDasharray && strokeDasharray.length > 0; }).length ); }).toBeGreaterThan(0); }); test('playback updates simulation status over time', async ({ page }) => { await page.goto('/kort7.html'); const status = page.locator('#status'); const initialText = await status.textContent(); const initialMatch = initialText.match(/Simuleret tid: ([\d.]+) s/); expect(initialMatch).not.toBeNull(); const initialTime = Number(initialMatch[1]); await page.waitForTimeout(1800); const text = await status.textContent(); const match = text.match(/Simuleret tid: ([\d.]+) s/); expect(match).not.toBeNull(); expect(Number(match[1])).toBeGreaterThan(initialTime + 0.5); }); test('shows off-map corner indicators for partial overlap and full cover', async ({ page }) => { await page.goto('/kort7.html'); await expect.poll(async () => page.locator('.offmap-indicator').count(), { timeout: 10000 }).toBeGreaterThan(0); const bil9 = page.locator('.offmap-indicator').filter({ hasText: 'Bil 9' }); const bil10 = page.locator('.offmap-indicator').filter({ hasText: 'Bil 10' }); const bil8 = page.locator('.offmap-indicator').filter({ hasText: 'Bil 8' }); await expect(bil9).toContainText('Mulig tilstedeværelse'); await expect(bil10).toContainText('dækker hele viewporten'); await expect(bil8).toHaveCount(0); }); test('shows matching alert text for off-map overlap states', async ({ page }) => { await page.goto('/kort7.html'); const alerts = page.locator('#presenceAlerts'); await expect(alerts).toContainText('Bil 9: mulig tilstedeværelse'); await expect(alerts).toContainText('Bil 10: usikkerhed dækker hele kortet'); await expect(alerts).not.toContainText('Bil 8'); }); });