mirror of
https://github.com/Freika/dawarich.git
synced 2026-01-11 09:41:40 -05:00
316 lines
12 KiB
JavaScript
316 lines
12 KiB
JavaScript
import { test, expect } from '@playwright/test'
|
|
import { closeOnboardingModal } from '../../helpers/navigation.js'
|
|
import { waitForMapLibre, waitForLoadingComplete } from '../helpers/setup.js'
|
|
|
|
test.describe('Area Selection in Maps V2', () => {
|
|
test.beforeEach(async ({ page }) => {
|
|
// Navigate to Maps V2 with specific date range that has data
|
|
await page.goto('/maps_v2?start_at=2025-10-15T00:00&end_at=2025-10-15T23:59')
|
|
await closeOnboardingModal(page)
|
|
await waitForMapLibre(page)
|
|
await waitForLoadingComplete(page)
|
|
// Wait a bit for data to load
|
|
await page.waitForTimeout(1000)
|
|
})
|
|
|
|
test('should enable area selection mode when clicking Select Area button', async ({ page }) => {
|
|
// Open settings panel and switch to Tools tab
|
|
await page.click('[data-action="click->maps-v2#toggleSettings"]')
|
|
await page.click('button[data-tab="tools"]')
|
|
|
|
// Click Select Area button
|
|
await page.click('[data-maps-v2-target="selectAreaButton"]')
|
|
|
|
// Wait a moment for UI to update
|
|
await page.waitForTimeout(100)
|
|
|
|
// Verify the button changes to Cancel Selection
|
|
const selectButton = page.locator('[data-maps-v2-target="selectAreaButton"]')
|
|
await expect(selectButton).toContainText('Cancel Selection', { timeout: 2000 })
|
|
|
|
// Verify cursor changes to crosshair (via canvas style)
|
|
const canvas = page.locator('canvas.maplibregl-canvas')
|
|
const cursorStyle = await canvas.evaluate(el => window.getComputedStyle(el).cursor)
|
|
expect(cursorStyle).toBe('crosshair')
|
|
|
|
// Verify toast notification appears
|
|
await expect(page.locator('.toast, [role="alert"]').filter({ hasText: 'Draw a rectangle' })).toBeVisible({ timeout: 5000 })
|
|
})
|
|
|
|
test('should draw selection rectangle when dragging mouse', async ({ page }) => {
|
|
// Open settings panel and switch to Tools tab
|
|
await page.click('[data-action="click->maps-v2#toggleSettings"]')
|
|
await page.click('button[data-tab="tools"]')
|
|
|
|
// Click Select Area button
|
|
await page.click('[data-maps-v2-target="selectAreaButton"]')
|
|
|
|
// Wait for selection mode to be enabled
|
|
await page.waitForTimeout(500)
|
|
|
|
// Check if selection layer has been added to map
|
|
const hasSelectionLayer = await page.evaluate(() => {
|
|
const element = document.querySelector('[data-controller="maps-v2"]')
|
|
const app = window.Stimulus || window.Application
|
|
const controller = app.getControllerForElementAndIdentifier(element, 'maps-v2')
|
|
return controller.selectionLayer !== undefined
|
|
})
|
|
expect(hasSelectionLayer).toBeTruthy()
|
|
|
|
// Get map canvas
|
|
const canvas = page.locator('canvas.maplibregl-canvas')
|
|
const box = await canvas.boundingBox()
|
|
|
|
// Draw selection rectangle with fewer steps to avoid timeout
|
|
await page.mouse.move(box.x + 100, box.y + 100)
|
|
await page.mouse.down()
|
|
await page.mouse.move(box.x + 300, box.y + 300, { steps: 3 })
|
|
await page.mouse.up()
|
|
|
|
// Wait for API call to complete (or timeout gracefully)
|
|
await page.waitForResponse(response =>
|
|
response.url().includes('/api/v1/points') &&
|
|
response.url().includes('min_longitude'),
|
|
{ timeout: 5000 }
|
|
).catch(() => null)
|
|
})
|
|
|
|
test('should show selection actions when points are selected', async ({ page }) => {
|
|
// Open settings panel and switch to Tools tab
|
|
await page.click('[data-action="click->maps-v2#toggleSettings"]')
|
|
await page.click('button[data-tab="tools"]')
|
|
|
|
// Click Select Area button
|
|
await page.click('[data-maps-v2-target="selectAreaButton"]')
|
|
|
|
// Get map canvas
|
|
const canvas = page.locator('canvas.maplibregl-canvas')
|
|
const box = await canvas.boundingBox()
|
|
|
|
// Draw selection rectangle over map center
|
|
await page.mouse.move(box.x + box.width / 2 - 100, box.y + box.height / 2 - 100)
|
|
await page.mouse.down()
|
|
await page.mouse.move(box.x + box.width / 2 + 100, box.y + box.height / 2 + 100, { steps: 10 })
|
|
await page.mouse.up()
|
|
|
|
// Wait for API call to complete
|
|
await page.waitForResponse(response =>
|
|
response.url().includes('/api/v1/points'),
|
|
{ timeout: 5000 }
|
|
).catch(() => null)
|
|
|
|
// Wait for potential updates
|
|
await page.waitForTimeout(1000)
|
|
|
|
// If points were found, verify UI updates
|
|
const selectionActions = page.locator('[data-maps-v2-target="selectionActions"]')
|
|
const isVisible = await selectionActions.isVisible().catch(() => false)
|
|
|
|
if (isVisible) {
|
|
// Verify delete button is visible and shows count
|
|
const deleteButton = page.locator('[data-maps-v2-target="deleteButtonText"]')
|
|
await expect(deleteButton).toBeVisible()
|
|
|
|
// Wait for button text to update with count
|
|
await expect(deleteButton).toContainText(/Delete \d+ Points?/, { timeout: 2000 })
|
|
|
|
// Verify the Select Area button has changed to Cancel Selection (at top of tools)
|
|
const selectButton = page.locator('[data-maps-v2-target="selectAreaButton"]')
|
|
await expect(selectButton).toContainText('Cancel Selection')
|
|
}
|
|
})
|
|
|
|
test('should cancel area selection', async ({ page }) => {
|
|
// Open settings panel and switch to Tools tab
|
|
await page.click('[data-action="click->maps-v2#toggleSettings"]')
|
|
await page.click('button[data-tab="tools"]')
|
|
|
|
// Click Select Area button
|
|
await page.click('[data-maps-v2-target="selectAreaButton"]')
|
|
|
|
// Wait for selection mode
|
|
await page.waitForTimeout(500)
|
|
|
|
// Get map canvas
|
|
const canvas = page.locator('canvas.maplibregl-canvas')
|
|
const box = await canvas.boundingBox()
|
|
|
|
// Draw selection rectangle with fewer steps
|
|
await page.mouse.move(box.x + box.width / 2 - 100, box.y + box.height / 2 - 100)
|
|
await page.mouse.down()
|
|
await page.mouse.move(box.x + box.width / 2 + 100, box.y + box.height / 2 + 100, { steps: 3 })
|
|
await page.mouse.up()
|
|
|
|
// Wait for API call
|
|
await page.waitForResponse(response =>
|
|
response.url().includes('/api/v1/points'),
|
|
{ timeout: 5000 }
|
|
).catch(() => null)
|
|
|
|
await page.waitForTimeout(500)
|
|
|
|
// Check if selection actions are visible
|
|
const selectionActions = page.locator('[data-maps-v2-target="selectionActions"]')
|
|
const isVisible = await selectionActions.isVisible().catch(() => false)
|
|
|
|
if (isVisible) {
|
|
// Click Cancel button (the red one at the top that replaced Select Area)
|
|
const cancelButton = page.locator('[data-maps-v2-target="selectAreaButton"]')
|
|
await expect(cancelButton).toContainText('Cancel Selection')
|
|
await cancelButton.click()
|
|
|
|
// Verify selection actions are hidden
|
|
await expect(selectionActions).toBeHidden()
|
|
|
|
// Verify Select Area button is restored
|
|
await expect(cancelButton).toContainText('Select Area')
|
|
await expect(cancelButton).toHaveClass(/btn-outline/)
|
|
await expect(cancelButton).not.toHaveClass(/btn-error/)
|
|
}
|
|
})
|
|
|
|
test('should display delete confirmation dialog', async ({ page }) => {
|
|
// Open settings panel and switch to Tools tab
|
|
await page.click('[data-action="click->maps-v2#toggleSettings"]')
|
|
await page.click('button[data-tab="tools"]')
|
|
|
|
// Click Select Area button
|
|
await page.click('[data-maps-v2-target="selectAreaButton"]')
|
|
|
|
// Get map canvas
|
|
const canvas = page.locator('canvas.maplibregl-canvas')
|
|
const box = await canvas.boundingBox()
|
|
|
|
// Draw selection rectangle
|
|
await page.mouse.move(box.x + box.width / 2 - 100, box.y + box.height / 2 - 100)
|
|
await page.mouse.down()
|
|
await page.mouse.move(box.x + box.width / 2 + 100, box.y + box.height / 2 + 100, { steps: 10 })
|
|
await page.mouse.up()
|
|
|
|
// Wait for API call
|
|
await page.waitForResponse(response =>
|
|
response.url().includes('/api/v1/points'),
|
|
{ timeout: 5000 }
|
|
).catch(() => null)
|
|
|
|
await page.waitForTimeout(500)
|
|
|
|
// Check if selection actions are visible
|
|
const selectionActions = page.locator('[data-maps-v2-target="selectionActions"]')
|
|
const isVisible = await selectionActions.isVisible().catch(() => false)
|
|
|
|
if (isVisible) {
|
|
// Setup dialog handler before clicking
|
|
let dialogShown = false
|
|
page.once('dialog', async dialog => {
|
|
dialogShown = true
|
|
expect(dialog.message()).toContain('Are you sure')
|
|
expect(dialog.message()).toContain('delete')
|
|
await dialog.dismiss()
|
|
})
|
|
|
|
// Click Delete button (text now includes count like "Delete 100 Points")
|
|
await page.locator('[data-maps-v2-target="deletePointsButton"]').click()
|
|
|
|
// Wait for dialog to be handled
|
|
await page.waitForTimeout(1000)
|
|
|
|
// Verify dialog was shown
|
|
expect(dialogShown).toBe(true)
|
|
|
|
// Verify selection is still active (because we dismissed)
|
|
await expect(selectionActions).toBeVisible()
|
|
}
|
|
})
|
|
|
|
test('should have API support for geographic bounds filtering', async ({ page }) => {
|
|
// Test that the backend accepts geographic bounds parameters
|
|
// by verifying the API call is made with the correct parameters when selecting an area
|
|
|
|
// Open settings panel and switch to Tools tab
|
|
await page.click('[data-action="click->maps-v2#toggleSettings"]')
|
|
await page.click('button[data-tab="tools"]')
|
|
|
|
// Click Select Area button
|
|
await page.click('[data-maps-v2-target="selectAreaButton"]')
|
|
await page.waitForTimeout(500)
|
|
|
|
// Get map canvas
|
|
const canvas = page.locator('canvas.maplibregl-canvas')
|
|
const box = await canvas.boundingBox()
|
|
|
|
// Set up network listener before drawing
|
|
let hasGeoBounds = false
|
|
|
|
page.on('request', request => {
|
|
if (request.url().includes('/api/v1/points')) {
|
|
const url = new URL(request.url(), 'http://localhost')
|
|
if (url.searchParams.has('min_longitude') &&
|
|
url.searchParams.has('max_longitude') &&
|
|
url.searchParams.has('min_latitude') &&
|
|
url.searchParams.has('max_latitude')) {
|
|
hasGeoBounds = true
|
|
}
|
|
}
|
|
})
|
|
|
|
// Draw selection rectangle
|
|
await page.mouse.move(box.x + 100, box.y + 100)
|
|
await page.mouse.down()
|
|
await page.mouse.move(box.x + 200, box.y + 200, { steps: 2 })
|
|
await page.mouse.up()
|
|
|
|
// Wait for API call
|
|
await page.waitForTimeout(2000)
|
|
|
|
// Verify the API was called with geographic bounds parameters
|
|
expect(hasGeoBounds).toBe(true)
|
|
})
|
|
|
|
test('should add selected points layer to map when points are selected', async ({ page }) => {
|
|
// Open settings panel and switch to Tools tab
|
|
await page.click('[data-action="click->maps-v2#toggleSettings"]')
|
|
await page.click('button[data-tab="tools"]')
|
|
|
|
// Click Select Area button
|
|
await page.click('[data-maps-v2-target="selectAreaButton"]')
|
|
|
|
// Get map canvas
|
|
const canvas = page.locator('canvas.maplibregl-canvas')
|
|
const box = await canvas.boundingBox()
|
|
|
|
// Draw selection rectangle
|
|
await page.mouse.move(box.x + box.width / 2 - 50, box.y + box.height / 2 - 50)
|
|
await page.mouse.down()
|
|
await page.mouse.move(box.x + box.width / 2 + 50, box.y + box.height / 2 + 50, { steps: 5 })
|
|
await page.mouse.up()
|
|
|
|
// Wait for API call
|
|
await page.waitForResponse(response =>
|
|
response.url().includes('/api/v1/points'),
|
|
{ timeout: 5000 }
|
|
).catch(() => null)
|
|
|
|
await page.waitForTimeout(500)
|
|
|
|
// Check if selected points layer exists
|
|
const hasSelectedPointsLayer = await page.evaluate(() => {
|
|
const element = document.querySelector('[data-controller="maps-v2"]')
|
|
const app = window.Stimulus || window.Application
|
|
const controller = app.getControllerForElementAndIdentifier(element, 'maps-v2')
|
|
return controller?.selectedPointsLayer !== undefined
|
|
})
|
|
|
|
// If points were selected, layer should exist
|
|
if (hasSelectedPointsLayer) {
|
|
// Verify layer is on the map
|
|
const layerExistsOnMap = await page.evaluate(() => {
|
|
const element = document.querySelector('[data-controller="maps-v2"]')
|
|
const app = window.Stimulus || window.Application
|
|
const controller = app.getControllerForElementAndIdentifier(element, 'maps-v2')
|
|
return controller?.map?.getLayer('selected-points') !== undefined
|
|
})
|
|
expect(layerExistsOnMap).toBeTruthy()
|
|
}
|
|
})
|
|
})
|