Playwright under e2e/, its own npm project so Meteor never sees the dependency (.meteorignore keeps the directory out of the bundle — a config file at the app root is otherwise eagerly loaded into the server and crashes it). Covers what the phase asked for: sign up / log in, creating a zone from the map and watching the union get painted on /subscriptions and /zones, removing it again, commenting on a fire, and switching language. The zone spec is the flow that froze staging on 2026-07-30 — it passes only if the server is still answering DDP while the union is recomputed. docker-compose.e2e.yml is a throwaway stack (Mongo on tmpfs, no named volume) so the destructive seeds cannot be pointed at anything real by accident; playwright.config.js refuses to start against the staging or production domains. i18n.spec.js leaves a test.fixme on a real bug found while writing it: the language chosen in the profile does not survive a page reload.
54 lines
2.6 KiB
JavaScript
54 lines
2.6 KiB
JavaScript
import { test, expect } from '@playwright/test';
|
|
import { signUp, addZoneThroughTheMap, waitForMap } from '../support/app.js';
|
|
|
|
// This is the flow that froze staging on 2026-07-30: subscribing to a zone makes
|
|
// the server recompute the union of every subscription, and while that ran on the
|
|
// main thread DDP stopped answering and every browser hung. A green run here means
|
|
// the page came back, the union reached the client, and the map drew it.
|
|
test.describe('suscripción a una zona y unión de zonas', () => {
|
|
test('creating a zone lists it and paints the union on both maps', async ({ page }) => {
|
|
await signUp(page);
|
|
await expect(page.getByText('No estás suscrito a fuegos en ninguna zona')).toBeVisible();
|
|
|
|
await addZoneThroughTheMap(page);
|
|
|
|
// Back on the zones page, the "you have no zones" warning is gone.
|
|
await expect(page.getByText('No estás suscrito a fuegos en ninguna zona')).toHaveCount(0);
|
|
|
|
// The union is a GeoJSON layer: leaflet draws it as an SVG path in the
|
|
// overlay pane. Nothing is drawn there until the server has recomputed and
|
|
// published it, so this also pins that the recompute finishes at all.
|
|
await waitForMap(page);
|
|
await expect(page.locator('.leaflet-overlay-pane path').first()).toBeVisible({ timeout: 60000 });
|
|
|
|
await page.goto('/zones');
|
|
await waitForMap(page);
|
|
await expect(page.locator('.leaflet-overlay-pane path').first()).toBeVisible({ timeout: 60000 });
|
|
});
|
|
|
|
test('the site keeps answering while the union is recomputed', async ({ page }) => {
|
|
await signUp(page);
|
|
await addZoneThroughTheMap(page);
|
|
|
|
// A DDP round trip right after the insert: if the union blocked the event
|
|
// loop again, this navigation would hang instead of rendering.
|
|
await page.goto('/fires');
|
|
await waitForMap(page);
|
|
await expect(page.locator('.leaflet-container').first()).toBeVisible();
|
|
});
|
|
|
|
// Removing is the other half of the same server-side path: it schedules a full
|
|
// recompute instead of an incremental merge.
|
|
test('a zone can be removed again from the map', async ({ page }) => {
|
|
await signUp(page);
|
|
await addZoneThroughTheMap(page);
|
|
await expect(page.getByText('En verde, áreas de las que recibirás alertas de fuegos')).toBeVisible();
|
|
|
|
await page.getByRole('button', { name: /Editar/i }).click();
|
|
await page.locator('.leaflet-marker-icon').first().click();
|
|
await expect(page.getByText('¿Estás seguro/a?')).toBeVisible();
|
|
await page.getByRole('button', { name: 'Sí', exact: true }).click();
|
|
|
|
await expect(page.getByText('No estás suscrito a fuegos en ninguna zona')).toBeVisible({ timeout: 60000 });
|
|
});
|
|
});
|