2025-11-05 15:09:37 -05:00
|
|
|
import { test, expect } from '@playwright/test';
|
|
|
|
|
import { navigateToMap } from '../helpers/navigation.js';
|
|
|
|
|
import { waitForMap, enableLayer } from '../helpers/map.js';
|
|
|
|
|
|
|
|
|
|
test.describe('Point Interactions', () => {
|
|
|
|
|
test.beforeEach(async ({ page }) => {
|
|
|
|
|
await navigateToMap(page);
|
|
|
|
|
await waitForMap(page);
|
|
|
|
|
await enableLayer(page, 'Points');
|
|
|
|
|
await page.waitForTimeout(1500);
|
|
|
|
|
|
|
|
|
|
// Pan map to ensure a marker is in viewport
|
|
|
|
|
await page.evaluate(() => {
|
|
|
|
|
const controller = window.Stimulus?.controllers.find(c => c.identifier === 'maps');
|
|
|
|
|
if (controller?.markers && controller.markers.length > 0) {
|
|
|
|
|
const firstMarker = controller.markers[0];
|
|
|
|
|
controller.map.setView([firstMarker[0], firstMarker[1]], 14);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
await page.waitForTimeout(1000);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test('should have draggable markers on the map', async ({ page }) => {
|
|
|
|
|
// Verify markers have draggable class
|
|
|
|
|
const marker = page.locator('.leaflet-marker-icon').first();
|
|
|
|
|
await expect(marker).toBeVisible();
|
|
|
|
|
|
|
|
|
|
// Check if marker has draggable class
|
|
|
|
|
const isDraggable = await marker.evaluate((el) => {
|
|
|
|
|
return el.classList.contains('leaflet-marker-draggable');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
expect(isDraggable).toBe(true);
|
|
|
|
|
|
|
|
|
|
// Verify marker position can be retrieved (required for drag operations)
|
|
|
|
|
const box = await marker.boundingBox();
|
|
|
|
|
expect(box).not.toBeNull();
|
|
|
|
|
expect(box.x).toBeGreaterThan(0);
|
|
|
|
|
expect(box.y).toBeGreaterThan(0);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test('should open popup when clicking a point', async ({ page }) => {
|
|
|
|
|
// Click on a marker with force to ensure interaction
|
|
|
|
|
const marker = page.locator('.leaflet-marker-icon').first();
|
|
|
|
|
await marker.click({ force: true });
|
|
|
|
|
await page.waitForTimeout(500);
|
|
|
|
|
|
|
|
|
|
// Verify popup is visible
|
|
|
|
|
const popup = page.locator('.leaflet-popup');
|
|
|
|
|
await expect(popup).toBeVisible();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test('should display correct popup content with point data', async ({ page }) => {
|
|
|
|
|
// Click on a marker
|
|
|
|
|
const marker = page.locator('.leaflet-marker-icon').first();
|
|
|
|
|
await marker.click({ force: true });
|
|
|
|
|
await page.waitForTimeout(500);
|
|
|
|
|
|
|
|
|
|
// Get popup content
|
|
|
|
|
const popupContent = page.locator('.leaflet-popup-content');
|
|
|
|
|
await expect(popupContent).toBeVisible();
|
|
|
|
|
|
|
|
|
|
const content = await popupContent.textContent();
|
|
|
|
|
|
|
|
|
|
// Verify all required fields are present
|
|
|
|
|
expect(content).toContain('Timestamp:');
|
|
|
|
|
expect(content).toContain('Latitude:');
|
|
|
|
|
expect(content).toContain('Longitude:');
|
|
|
|
|
expect(content).toContain('Altitude:');
|
|
|
|
|
expect(content).toContain('Speed:');
|
|
|
|
|
expect(content).toContain('Battery:');
|
|
|
|
|
expect(content).toContain('Id:');
|
|
|
|
|
});
|
|
|
|
|
|
2025-11-19 13:17:30 -05:00
|
|
|
test('should delete a point and redraw route @destructive', async ({ page }) => {
|
2025-11-05 15:09:37 -05:00
|
|
|
// Enable Routes layer to verify route redraw
|
|
|
|
|
await enableLayer(page, 'Routes');
|
|
|
|
|
await page.waitForTimeout(1000);
|
|
|
|
|
|
|
|
|
|
// Count initial markers and get point ID
|
|
|
|
|
const initialData = await page.evaluate(() => {
|
|
|
|
|
const controller = window.Stimulus?.controllers.find(c => c.identifier === 'maps');
|
|
|
|
|
const markerCount = controller?.markersLayer ? Object.keys(controller.markersLayer._layers).length : 0;
|
|
|
|
|
const polylineCount = controller?.polylinesLayer ? Object.keys(controller.polylinesLayer._layers).length : 0;
|
|
|
|
|
return { markerCount, polylineCount };
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Click on a marker to open popup
|
|
|
|
|
const marker = page.locator('.leaflet-marker-icon').first();
|
|
|
|
|
await marker.click({ force: true });
|
|
|
|
|
await page.waitForTimeout(500);
|
|
|
|
|
|
|
|
|
|
// Verify popup opened
|
|
|
|
|
await expect(page.locator('.leaflet-popup')).toBeVisible();
|
|
|
|
|
|
|
|
|
|
// Get the point ID from popup before deleting
|
|
|
|
|
const pointId = await page.locator('.leaflet-popup-content').evaluate((content) => {
|
|
|
|
|
const match = content.textContent.match(/Id:\s*(\d+)/);
|
|
|
|
|
return match ? match[1] : null;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
expect(pointId).not.toBeNull();
|
|
|
|
|
|
|
|
|
|
// Find delete button (might be a link or button with "Delete" text)
|
|
|
|
|
const deleteButton = page.locator('.leaflet-popup-content a:has-text("Delete"), .leaflet-popup-content button:has-text("Delete")').first();
|
|
|
|
|
|
|
|
|
|
const hasDeleteButton = await deleteButton.count() > 0;
|
|
|
|
|
|
|
|
|
|
if (hasDeleteButton) {
|
|
|
|
|
// Handle confirmation dialog
|
|
|
|
|
page.once('dialog', dialog => {
|
|
|
|
|
expect(dialog.message()).toContain('delete');
|
|
|
|
|
dialog.accept();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
await deleteButton.click();
|
|
|
|
|
await page.waitForTimeout(2000); // Wait for deletion to complete
|
|
|
|
|
|
|
|
|
|
// Verify marker count decreased
|
|
|
|
|
const finalData = await page.evaluate(() => {
|
|
|
|
|
const controller = window.Stimulus?.controllers.find(c => c.identifier === 'maps');
|
|
|
|
|
const markerCount = controller?.markersLayer ? Object.keys(controller.markersLayer._layers).length : 0;
|
|
|
|
|
const polylineCount = controller?.polylinesLayer ? Object.keys(controller.polylinesLayer._layers).length : 0;
|
|
|
|
|
return { markerCount, polylineCount };
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Verify at least one marker was removed
|
|
|
|
|
expect(finalData.markerCount).toBeLessThan(initialData.markerCount);
|
|
|
|
|
|
|
|
|
|
// Verify routes still exist (they should be redrawn)
|
|
|
|
|
expect(finalData.polylineCount).toBeGreaterThanOrEqual(0);
|
|
|
|
|
|
|
|
|
|
// Verify success flash message appears
|
|
|
|
|
const flashMessage = page.locator('#flash-messages [role="alert"]').filter({ hasText: /deleted successfully/i });
|
|
|
|
|
await expect(flashMessage).toBeVisible({ timeout: 5000 });
|
|
|
|
|
} else {
|
|
|
|
|
// If no delete button, just verify the test setup worked
|
|
|
|
|
console.log('No delete button found in popup - this might be expected based on permissions');
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
});
|