import { test, expect } from '@playwright/test' import { closeOnboardingModal } from '../../helpers/navigation.js' import { getLayerVisibility } from '../helpers/setup.js' test.describe('Map Settings', () => { test.beforeEach(async ({ page }) => { await page.goto('/map/v2?start_at=2025-10-15T00:00&end_at=2025-10-15T23:59') await closeOnboardingModal(page) await page.waitForTimeout(2000) }) test.describe('Settings Panel', () => { test('opens and closes settings panel', async ({ page }) => { const panel = page.locator('[data-maps--maplibre-target="settingsPanel"]') // Verify panel exists but is not open initially await expect(panel).toBeVisible() await expect(panel).not.toHaveClass(/open/) // Open the panel const settingsButton = page.locator('button[title="Open map settings"]') await settingsButton.click() // Wait for the panel to have the open class await expect(panel).toHaveClass(/open/, { timeout: 3000 }) // Close the panel const closeButton = page.locator('button[title="Close panel"]') await closeButton.click() await expect(panel).not.toHaveClass(/open/, { timeout: 3000 }) }) test('displays layer controls in settings', async ({ page }) => { await page.click('button[title="Open map settings"]') await page.waitForTimeout(400) await page.click('button[data-tab="layers"]') await page.waitForTimeout(300) const pointsToggle = page.locator('label:has-text("Points")').first().locator('input.toggle') const routesToggle = page.locator('label:has-text("Routes")').first().locator('input.toggle') await expect(pointsToggle).toBeVisible() await expect(routesToggle).toBeVisible() }) test('has tabs for different settings sections', async ({ page }) => { await page.click('button[title="Open map settings"]') await page.waitForTimeout(400) const searchTab = page.locator('button[data-tab="search"]') const layersTab = page.locator('button[data-tab="layers"]') const settingsTab = page.locator('button[data-tab="settings"]') await expect(searchTab).toBeVisible() await expect(layersTab).toBeVisible() await expect(settingsTab).toBeVisible() }) }) test.describe('Layer Toggles', () => { test('points layer visibility matches toggle state', async ({ page }) => { // Wait for points layer to exist await page.waitForFunction(() => { const element = document.querySelector('[data-controller*="maps--maplibre"]') const app = window.Stimulus || window.Application const controller = app?.getControllerForElementAndIdentifier(element, 'maps--maplibre') return controller?.map?.getLayer('points') !== undefined }, { timeout: 5000 }).catch(() => false) const isVisible = await getLayerVisibility(page, 'points') await page.click('button[title="Open map settings"]') await page.waitForTimeout(400) await page.click('button[data-tab="layers"]') await page.waitForTimeout(300) const pointsToggle = page.locator('label:has-text("Points")').first().locator('input.toggle') const toggleState = await pointsToggle.isChecked() expect(isVisible).toBe(toggleState) }) test('routes layer visibility matches toggle state', async ({ page }) => { // Wait for routes layer to exist await page.waitForFunction(() => { const element = document.querySelector('[data-controller*="maps--maplibre"]') const app = window.Stimulus || window.Application const controller = app?.getControllerForElementAndIdentifier(element, 'maps--maplibre') return controller?.map?.getLayer('routes') !== undefined }, { timeout: 5000 }).catch(() => false) const isVisible = await getLayerVisibility(page, 'routes') await page.click('button[title="Open map settings"]') await page.waitForTimeout(400) await page.click('button[data-tab="layers"]') await page.waitForTimeout(300) const routesToggle = page.locator('label:has-text("Routes")').first().locator('input.toggle') const toggleState = await routesToggle.isChecked() expect(isVisible).toBe(toggleState) }) test('can toggle points layer', async ({ page }) => { await page.click('button[title="Open map settings"]') await page.waitForTimeout(400) await page.click('button[data-tab="layers"]') await page.waitForTimeout(300) const pointsLabel = page.locator('label:has-text("Points")').first() const pointsToggle = pointsLabel.locator('input.toggle') const initialState = await pointsToggle.isChecked() await pointsLabel.click() await page.waitForTimeout(500) const newState = await pointsToggle.isChecked() expect(newState).toBe(!initialState) await pointsLabel.click() await page.waitForTimeout(500) const finalState = await pointsToggle.isChecked() expect(finalState).toBe(initialState) }) test('can toggle routes layer', async ({ page }) => { await page.click('button[title="Open map settings"]') await page.waitForTimeout(400) await page.click('button[data-tab="layers"]') await page.waitForTimeout(300) const routesLabel = page.locator('label:has-text("Routes")').first() const routesToggle = routesLabel.locator('input.toggle') const initialState = await routesToggle.isChecked() await routesLabel.click() await page.waitForTimeout(500) const newState = await routesToggle.isChecked() expect(newState).toBe(!initialState) }) test('multiple layers can be toggled simultaneously', async ({ page }) => { await page.click('button[title="Open map settings"]') await page.waitForTimeout(400) await page.click('button[data-tab="layers"]') await page.waitForTimeout(300) const pointsToggle = page.locator('label:has-text("Points")').first().locator('input.toggle') const routesToggle = page.locator('label:has-text("Routes")').first().locator('input.toggle') if (!(await pointsToggle.isChecked())) { await pointsToggle.check() await page.waitForTimeout(500) } if (!(await routesToggle.isChecked())) { await routesToggle.check() await page.waitForTimeout(500) } const pointsVisible = await getLayerVisibility(page, 'points') const routesVisible = await getLayerVisibility(page, 'routes') expect(pointsVisible).toBe(true) expect(routesVisible).toBe(true) }) test('rapidly toggling multiple layers without page reload persists all changes', async ({ page }) => { await page.click('button[title="Open map settings"]') await page.waitForTimeout(400) await page.click('button[data-tab="layers"]') await page.waitForTimeout(300) // Get all layer toggles const pointsToggle = page.locator('label:has-text("Points")').first().locator('input.toggle') const routesToggle = page.locator('label:has-text("Routes")').first().locator('input.toggle') const heatmapToggle = page.locator('label:has-text("Heatmap")').first().locator('input.toggle') // Record initial states const initialPoints = await pointsToggle.isChecked() const initialRoutes = await routesToggle.isChecked() const initialHeatmap = await heatmapToggle.isChecked() // Rapidly toggle all three layers without waiting between toggles await pointsToggle.click() await routesToggle.click() await heatmapToggle.click() // Wait for settings to be saved (backend saves are async) await page.waitForTimeout(1000) // Verify toggle states changed expect(await pointsToggle.isChecked()).toBe(!initialPoints) expect(await routesToggle.isChecked()).toBe(!initialRoutes) expect(await heatmapToggle.isChecked()).toBe(!initialHeatmap) // Verify settings persisted in localStorage const settings = await page.evaluate(() => { return localStorage.getItem('dawarich-maps-maplibre-settings') }) if (settings) { const parsed = JSON.parse(settings) expect(parsed.pointsVisible).toBe(!initialPoints) expect(parsed.routesVisible).toBe(!initialRoutes) expect(parsed.heatmapEnabled).toBe(!initialHeatmap) // Verify enabledMapLayers array is also updated correctly if (!initialPoints) { expect(parsed.enabledMapLayers).toContain('Points') } else { expect(parsed.enabledMapLayers).not.toContain('Points') } if (!initialRoutes) { expect(parsed.enabledMapLayers).toContain('Routes') } else { expect(parsed.enabledMapLayers).not.toContain('Routes') } if (!initialHeatmap) { expect(parsed.enabledMapLayers).toContain('Heatmap') } else { expect(parsed.enabledMapLayers).not.toContain('Heatmap') } } // Toggle them back rapidly await pointsToggle.click() await routesToggle.click() await heatmapToggle.click() // Wait for settings to be saved await page.waitForTimeout(1000) // Verify all states returned to initial values expect(await pointsToggle.isChecked()).toBe(initialPoints) expect(await routesToggle.isChecked()).toBe(initialRoutes) expect(await heatmapToggle.isChecked()).toBe(initialHeatmap) }) }) test.describe('Settings Persistence', () => { test('layer toggle state persists in localStorage', async ({ page }) => { await page.click('button[title="Open map settings"]') await page.waitForTimeout(400) await page.click('button[data-tab="layers"]') await page.waitForTimeout(300) const pointsToggle = page.locator('label:has-text("Points")').first().locator('input.toggle') const initialState = await pointsToggle.isChecked() // Toggle to trigger a save await pointsToggle.click() await page.waitForTimeout(500) // Check localStorage after a toggle action const settings = await page.evaluate(() => { return localStorage.getItem('dawarich-maps-maplibre-settings') }) // Settings might be saved to backend only, not localStorage if (settings) { const parsed = JSON.parse(settings) // After toggling, the state should be opposite of initial expect(parsed.pointsVisible).toBe(!initialState) } else { // If no localStorage, verify the toggle state changed expect(await pointsToggle.isChecked()).toBe(!initialState) } }) }) test.describe('Advanced Settings', () => { test('displays advanced settings options', async ({ page }) => { await page.click('button[title="Open map settings"]') await page.waitForTimeout(400) await page.click('button[data-tab="settings"]') await page.waitForTimeout(300) const panel = page.locator('[data-tab-content="settings"]') await expect(panel).toBeVisible() }) }) })