dawarich/e2e/map/map-add-visit.spec.js
2025-11-05 21:09:37 +01:00

260 lines
10 KiB
JavaScript

import { test, expect } from '@playwright/test';
import { navigateToMap } from '../helpers/navigation.js';
import { waitForMap } from '../helpers/map.js';
/**
* Helper to wait for add visit controller to be fully initialized
*/
async function waitForAddVisitController(page) {
await page.waitForTimeout(2000); // Wait for controller to connect and attach handlers
}
test.describe('Add Visit Control', () => {
test.beforeEach(async ({ page }) => {
await navigateToMap(page);
await waitForMap(page);
await waitForAddVisitController(page);
});
test('should show add visit button control', async ({ page }) => {
const addVisitButton = page.locator('.add-visit-button');
await expect(addVisitButton).toBeVisible();
});
test('should enable add visit mode when clicked', async ({ page }) => {
const addVisitButton = page.locator('.add-visit-button');
await addVisitButton.click();
await page.waitForTimeout(1000);
// Verify flash message appears
const flashMessage = page.locator('#flash-messages [role="alert"]:has-text("Click on the map")');
await expect(flashMessage).toBeVisible({ timeout: 5000 });
// Verify cursor changed to crosshair
const cursor = await page.evaluate(() => {
const container = document.querySelector('#map [data-maps-target="container"]');
return container?.style.cursor;
});
expect(cursor).toBe('crosshair');
// Verify button has active state (background color applied)
const hasActiveStyle = await addVisitButton.evaluate((el) => {
return el.style.backgroundColor !== '';
});
expect(hasActiveStyle).toBe(true);
});
test('should open popup form when map is clicked', async ({ page }) => {
const addVisitButton = page.locator('.add-visit-button');
await addVisitButton.click();
await page.waitForTimeout(500);
// Click on map - use bottom left corner which is less likely to have points
const mapContainer = page.locator('#map [data-maps-target="container"]');
const bbox = await mapContainer.boundingBox();
await page.mouse.click(bbox.x + bbox.width * 0.2, bbox.y + bbox.height * 0.8);
await page.waitForTimeout(1000);
// Verify popup is visible
const popup = page.locator('.leaflet-popup');
await expect(popup).toBeVisible({ timeout: 10000 });
// Verify popup contains the add visit form
await expect(popup.locator('h3:has-text("Add New Visit")')).toBeVisible();
// Verify marker appears (📍 emoji with class add-visit-marker)
const marker = page.locator('.add-visit-marker');
await expect(marker).toBeVisible();
});
test('should display correct form content in popup', async ({ page }) => {
// Enable mode and click map
await page.locator('.add-visit-button').click();
await page.waitForTimeout(500);
const mapContainer = page.locator('#map [data-maps-target="container"]');
const bbox = await mapContainer.boundingBox();
await page.mouse.click(bbox.x + bbox.width * 0.2, bbox.y + bbox.height * 0.8);
await page.waitForTimeout(1000);
// Verify popup content has all required elements
const popupContent = page.locator('.leaflet-popup-content');
await expect(popupContent.locator('h3:has-text("Add New Visit")')).toBeVisible();
await expect(popupContent.locator('input#visit-name')).toBeVisible();
await expect(popupContent.locator('input#visit-start')).toBeVisible();
await expect(popupContent.locator('input#visit-end')).toBeVisible();
await expect(popupContent.locator('button:has-text("Create Visit")')).toBeVisible();
await expect(popupContent.locator('button:has-text("Cancel")')).toBeVisible();
// Verify name field has focus
const nameFieldFocused = await page.evaluate(() => {
return document.activeElement?.id === 'visit-name';
});
expect(nameFieldFocused).toBe(true);
// Verify start and end time have default values
const startValue = await page.locator('input#visit-start').inputValue();
const endValue = await page.locator('input#visit-end').inputValue();
expect(startValue).toBeTruthy();
expect(endValue).toBeTruthy();
});
test('should hide popup and remove marker when cancel is clicked', async ({ page }) => {
// Enable mode and click map
await page.locator('.add-visit-button').click();
await page.waitForTimeout(500);
const mapContainer = page.locator('#map [data-maps-target="container"]');
const bbox = await mapContainer.boundingBox();
await page.mouse.click(bbox.x + bbox.width * 0.2, bbox.y + bbox.height * 0.8);
await page.waitForTimeout(1000);
// Verify popup and marker exist
await expect(page.locator('.leaflet-popup')).toBeVisible();
await expect(page.locator('.add-visit-marker')).toBeVisible();
// Click cancel button
await page.locator('#cancel-visit').click();
await page.waitForTimeout(500);
// Verify popup is hidden
const popupVisible = await page.locator('.leaflet-popup').isVisible().catch(() => false);
expect(popupVisible).toBe(false);
// Verify marker is removed
const markerCount = await page.locator('.add-visit-marker').count();
expect(markerCount).toBe(0);
// Verify cursor is reset to default
const cursor = await page.evaluate(() => {
const container = document.querySelector('#map [data-maps-target="container"]');
return container?.style.cursor;
});
expect(cursor).toBe('');
// Verify mode was exited (cursor should be reset)
const cursorReset = await page.evaluate(() => {
const container = document.querySelector('#map [data-maps-target="container"]');
return container?.style.cursor === '';
});
expect(cursorReset).toBe(true);
});
test('should create visit and show marker on map when submitted', async ({ page }) => {
// Get initial confirmed visit count
const initialCount = await page.evaluate(() => {
const controller = window.Stimulus?.controllers.find(c => c.identifier === 'maps');
if (controller?.visitsManager?.confirmedVisitCircles?._layers) {
return Object.keys(controller.visitsManager.confirmedVisitCircles._layers).length;
}
return 0;
});
// Enable mode and click map
await page.locator('.add-visit-button').click();
await page.waitForTimeout(500);
const mapContainer = page.locator('#map [data-maps-target="container"]');
const bbox = await mapContainer.boundingBox();
await page.mouse.click(bbox.x + bbox.width * 0.2, bbox.y + bbox.height * 0.8);
await page.waitForTimeout(1000);
// Fill form with unique visit name
const visitName = `E2E Test Visit ${Date.now()}`;
await page.locator('#visit-name').fill(visitName);
// Submit form
await page.locator('button:has-text("Create Visit")').click();
await page.waitForTimeout(2000);
// Verify success message
const flashMessage = page.locator('#flash-messages [role="alert"]:has-text("created successfully")');
await expect(flashMessage).toBeVisible({ timeout: 5000 });
// Verify popup is closed
const popupVisible = await page.locator('.leaflet-popup').isVisible().catch(() => false);
expect(popupVisible).toBe(false);
// Verify confirmed visit marker count increased
const finalCount = await page.evaluate(() => {
const controller = window.Stimulus?.controllers.find(c => c.identifier === 'maps');
if (controller?.visitsManager?.confirmedVisitCircles?._layers) {
return Object.keys(controller.visitsManager.confirmedVisitCircles._layers).length;
}
return 0;
});
expect(finalCount).toBeGreaterThan(initialCount);
});
test('should disable add visit mode when clicked second time', async ({ page }) => {
const addVisitButton = page.locator('.add-visit-button');
// First click - enable mode
await addVisitButton.click();
await page.waitForTimeout(500);
// Verify mode is enabled
const cursorEnabled = await page.evaluate(() => {
const container = document.querySelector('#map [data-maps-target="container"]');
return container?.style.cursor === 'crosshair';
});
expect(cursorEnabled).toBe(true);
// Second click - disable mode
await addVisitButton.click();
await page.waitForTimeout(500);
// Verify cursor is reset
const cursorDisabled = await page.evaluate(() => {
const container = document.querySelector('#map [data-maps-target="container"]');
return container?.style.cursor;
});
expect(cursorDisabled).toBe('');
// Verify mode was exited by checking if we can click map without creating marker
const isAddingVisit = await page.evaluate(() => {
const controller = window.Stimulus?.controllers.find(c => c.identifier === 'add-visit');
return controller?.isAddingVisit === true;
});
expect(isAddingVisit).toBe(false);
});
test('should ensure only one visit popup is open at a time', async ({ page }) => {
const addVisitButton = page.locator('.add-visit-button');
await addVisitButton.click();
await page.waitForTimeout(500);
const mapContainer = page.locator('#map [data-maps-target="container"]');
const bbox = await mapContainer.boundingBox();
// Click first location on map
await page.mouse.click(bbox.x + bbox.width * 0.3, bbox.y + bbox.height * 0.3);
await page.waitForTimeout(500);
// Verify first popup exists
let popupCount = await page.locator('.leaflet-popup').count();
expect(popupCount).toBe(1);
// Get the content of first popup to verify it exists
const firstPopupContent = await page.locator('.leaflet-popup-content input#visit-name').count();
expect(firstPopupContent).toBe(1);
// Click second location on map
await page.mouse.click(bbox.x + bbox.width * 0.7, bbox.y + bbox.height * 0.7);
await page.waitForTimeout(500);
// Verify still only one popup exists (old one was closed, new one opened)
popupCount = await page.locator('.leaflet-popup').count();
expect(popupCount).toBe(1);
// Verify the popup contains the add visit form (not some other popup)
const popupContent = page.locator('.leaflet-popup-content');
await expect(popupContent.locator('h3:has-text("Add New Visit")')).toBeVisible();
await expect(popupContent.locator('input#visit-name')).toBeVisible();
// Verify only one marker exists
const markerCount = await page.locator('.add-visit-marker').count();
expect(markerCount).toBe(1);
});
});