import { test, expect } from '@playwright/test'; import { navigateToMap, closeOnboardingModal } from '../helpers/navigation.js'; import { waitForMap, enableLayer, clickSuggestedVisit } from '../helpers/map.js'; test.describe('Suggested Visit Interactions', () => { test.beforeEach(async ({ page }) => { await navigateToMap(page); await waitForMap(page); // Navigate to a date range that includes visits (last month to now) const toggleButton = page.locator('button[data-action*="map-controls#toggle"]'); const isPanelVisible = await page.locator('[data-map-controls-target="panel"]').isVisible(); if (!isPanelVisible) { await toggleButton.click(); await page.waitForTimeout(300); } // Set date range to last month await page.click('a:has-text("Last month")'); await page.waitForTimeout(2000); await closeOnboardingModal(page); await waitForMap(page); await enableLayer(page, 'Suggested'); await page.waitForTimeout(2000); // Pan map to ensure a visit marker is in viewport await page.evaluate(() => { const controller = window.Stimulus?.controllers.find(c => c.identifier === 'maps'); if (controller?.visitsManager?.suggestedVisitCircles) { const layers = controller.visitsManager.suggestedVisitCircles._layers; const firstVisit = Object.values(layers)[0]; if (firstVisit && firstVisit._latlng) { controller.map.setView(firstVisit._latlng, 14); } } }); await page.waitForTimeout(1000); }); test('should click on a suggested visit and open popup', async ({ page }) => { // Debug: Check what visit circles exist const allCircles = await page.evaluate(() => { const controller = window.Stimulus?.controllers.find(c => c.identifier === 'maps'); if (controller?.visitsManager?.suggestedVisitCircles?._layers) { const layers = controller.visitsManager.suggestedVisitCircles._layers; return { count: Object.keys(layers).length, hasLayers: Object.keys(layers).length > 0 }; } return { count: 0, hasLayers: false }; }); // If we have visits in the layer but can't find DOM elements, use coordinates if (!allCircles.hasLayers) { console.log('No suggested visits found - skipping test'); return; } // Click on the visit using map coordinates const visitClicked = await clickSuggestedVisit(page); if (!visitClicked) { console.log('Could not click suggested visit - skipping test'); return; } await page.waitForTimeout(500); // Verify popup is visible const popup = page.locator('.leaflet-popup'); await expect(popup).toBeVisible(); }); test('should display correct content in suggested visit popup', async ({ page }) => { // Click visit programmatically const visitClicked = await clickSuggestedVisit(page); if (!visitClicked) { console.log('No suggested visits found - skipping test'); return; } await page.waitForTimeout(500); // Get popup content const popupContent = page.locator('.leaflet-popup-content'); await expect(popupContent).toBeVisible(); const content = await popupContent.textContent(); // Verify visit information is present expect(content).toMatch(/Visit|Place|Duration|Started|Ended|Suggested/i); }); test('should confirm suggested visit @destructive', async ({ page }) => { // Click visit programmatically const visitClicked = await clickSuggestedVisit(page); if (!visitClicked) { console.log('No suggested visits found - skipping test'); return; } await page.waitForTimeout(500); // Look for confirm button in popup const confirmButton = page.locator('.leaflet-popup-content button:has-text("Confirm")').first(); const hasConfirmButton = await confirmButton.count() > 0; if (!hasConfirmButton) { console.log('No confirm button found - skipping test'); return; } // Get initial counts for both suggested and confirmed visits const initialCounts = await page.evaluate(() => { const controller = window.Stimulus?.controllers.find(c => c.identifier === 'maps'); return { suggested: controller?.visitsManager?.suggestedVisitCircles?._layers ? Object.keys(controller.visitsManager.suggestedVisitCircles._layers).length : 0, confirmed: controller?.visitsManager?.confirmedVisitCircles?._layers ? Object.keys(controller.visitsManager.confirmedVisitCircles._layers).length : 0 }; }); // Click confirm button await confirmButton.click(); await page.waitForTimeout(1500); // Verify the marker changed from yellow to green (suggested to confirmed) const finalCounts = await page.evaluate(() => { const controller = window.Stimulus?.controllers.find(c => c.identifier === 'maps'); return { suggested: controller?.visitsManager?.suggestedVisitCircles?._layers ? Object.keys(controller.visitsManager.suggestedVisitCircles._layers).length : 0, confirmed: controller?.visitsManager?.confirmedVisitCircles?._layers ? Object.keys(controller.visitsManager.confirmedVisitCircles._layers).length : 0 }; }); // Verify suggested visit count decreased expect(finalCounts.suggested).toBeLessThan(initialCounts.suggested); // Verify confirmed visit count increased (marker changed from yellow to green) expect(finalCounts.confirmed).toBeGreaterThan(initialCounts.confirmed); // Verify popup is closed after confirmation const popupVisible = await page.locator('.leaflet-popup').isVisible().catch(() => false); expect(popupVisible).toBe(false); }); test('should decline suggested visit @destructive', async ({ page }) => { // Click visit programmatically const visitClicked = await clickSuggestedVisit(page); if (!visitClicked) { console.log('No suggested visits found - skipping test'); return; } await page.waitForTimeout(500); // Look for decline button in popup const declineButton = page.locator('.leaflet-popup-content button:has-text("Decline")').first(); const hasDeclineButton = await declineButton.count() > 0; if (!hasDeclineButton) { console.log('No decline button found - skipping test'); return; } // Get initial suggested visit count const initialCount = await page.evaluate(() => { const controller = window.Stimulus?.controllers.find(c => c.identifier === 'maps'); if (controller?.visitsManager?.suggestedVisitCircles?._layers) { return Object.keys(controller.visitsManager.suggestedVisitCircles._layers).length; } return 0; }); // Verify popup is visible before decline await expect(page.locator('.leaflet-popup')).toBeVisible(); // Click decline button await declineButton.click(); await page.waitForTimeout(1500); // Verify popup is removed from map const popupVisible = await page.locator('.leaflet-popup').isVisible().catch(() => false); expect(popupVisible).toBe(false); // Verify marker is removed from map (suggested visit count decreased) const finalCount = await page.evaluate(() => { const controller = window.Stimulus?.controllers.find(c => c.identifier === 'maps'); if (controller?.visitsManager?.suggestedVisitCircles?._layers) { return Object.keys(controller.visitsManager.suggestedVisitCircles._layers).length; } return 0; }); expect(finalCount).toBeLessThan(initialCount); // Verify the yellow marker is no longer visible on the map const yellowMarkerCount = await page.locator('.leaflet-interactive[stroke="#f59e0b"]').count(); expect(yellowMarkerCount).toBeLessThan(initialCount); }); test('should change place in dropdown for suggested visit', async ({ page }) => { const visitCircle = page.locator('.leaflet-interactive[stroke="#f59e0b"]').first(); const hasVisits = await visitCircle.count() > 0; if (!hasVisits) { console.log('No suggested visits found - skipping test'); return; } await visitCircle.click({ force: true }); await page.waitForTimeout(500); // Look for place dropdown/select in popup const placeSelect = page.locator('.leaflet-popup-content select, .leaflet-popup-content [role="combobox"]').first(); const hasPlaceDropdown = await placeSelect.count() > 0; if (!hasPlaceDropdown) { console.log('No place dropdown found - skipping test'); return; } // Select a different option await placeSelect.selectOption({ index: 1 }); await page.waitForTimeout(300); // Verify the selection changed const newValue = await placeSelect.inputValue(); expect(newValue).toBeTruthy(); }); test('should delete suggested visit from map @destructive', async ({ page }) => { const visitCircle = page.locator('.leaflet-interactive[stroke="#f59e0b"]').first(); const hasVisits = await visitCircle.count() > 0; if (!hasVisits) { console.log('No suggested visits found - skipping test'); return; } // Count initial visits const initialVisitCount = await page.evaluate(() => { const controller = window.Stimulus?.controllers.find(c => c.identifier === 'maps'); if (controller?.visitsManager?.suggestedVisitCircles?._layers) { return Object.keys(controller.visitsManager.suggestedVisitCircles._layers).length; } return 0; }); await visitCircle.click({ force: true }); await page.waitForTimeout(500); // Find delete button const deleteButton = page.locator('.leaflet-popup-content button:has-text("Delete"), .leaflet-popup-content a:has-text("Delete")').first(); const hasDeleteButton = await deleteButton.count() > 0; if (!hasDeleteButton) { console.log('No delete button found - skipping test'); return; } // Handle confirmation dialog page.once('dialog', dialog => { expect(dialog.message()).toMatch(/delete|remove/i); dialog.accept(); }); await deleteButton.click(); await page.waitForTimeout(2000); // Verify visit count decreased const finalVisitCount = await page.evaluate(() => { const controller = window.Stimulus?.controllers.find(c => c.identifier === 'maps'); if (controller?.visitsManager?.suggestedVisitCircles?._layers) { return Object.keys(controller.visitsManager.suggestedVisitCircles._layers).length; } return 0; }); expect(finalVisitCount).toBeLessThan(initialVisitCount); }); });