leaflet_svelte/tests/e2e/bbox.spec.ts
2026-08-03 22:12:32 +09:00

123 lines
4.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { test, expect, login, sceneObjectCount } from './fixtures';
/**
* Browser-side checks for the restricted-area box. The geometry itself is
* covered in tests/unit/boundingBox.spec.ts, which runs in Node against the pure
* module; what only a browser can answer is whether the thing rasterises and
* what the operator ends up reading on screen.
*/
test.beforeEach(async ({ context }) => {
await login(context);
});
/** Seed one workspace at the given launch point, run it, and draw its box. */
async function runAt(page: import('@playwright/test').Page, lat: number, lng: number) {
await page.goto('/');
await page.evaluate(
({ lat, lng }) => {
const ws = {
id: crypto.randomUUID(),
name: `bbox-${lat}`,
color: '#dc3545',
opacity: 1,
visible: true,
flightParameters: {
ascent_rate: 5,
burst_altitude: 30000,
dataset: '',
descent_rate: 5,
format: 'json',
launch_altitude: 0,
launch_latitude: lat,
launch_longitude: lng,
profile: 'standard_profile',
version: 2,
},
launchDate: new Date().toISOString().split('T')[0],
launchTime: '12:00:00',
result: null,
bboxMargin: 5,
bboxVisible: false,
};
localStorage.setItem('workspaces', JSON.stringify({ items: [ws], activeId: ws.id }));
},
{ lat, lng },
);
await page.goto('/predict');
await page
.locator('.map-container canvas')
.first()
.waitFor({ state: 'attached', timeout: 60_000 });
const panel = page.locator('.panel-container-right');
await panel
.locator('.workspace-row')
.first()
.getByRole('button', { name: /Рассчитать|Run/ })
.click();
await expect
.poll(() => sceneObjectCount(page, 'ws/'), { timeout: 90_000, intervals: [1000, 2000, 3000] })
.toBeGreaterThan(0);
await panel.getByRole('button', { name: /Построить рамку|Generate bounding box/ }).click();
await expect.poll(() => sceneObjectCount(page, 'bbox'), { timeout: 15_000 }).toBeGreaterThan(0);
return panel;
}
/**
* Regression: the box must actually rasterise.
*
* An earlier attempt made a pole-touching box circumpolar with west=-180 and
* east=180. Both meridional edges then lay on the antimeridian, and Cesium's
* splitLongitude pass — which cuts geometry at the IDL — produced mismatched
* attribute lists and killed the render loop:
*
* DeveloperError: All attribute lists must have the same number of attributes.
* at k.splitLongitude / S.combineGeometry
*
* Assertions on polyline.positions could not see this, because that is the entity
* definition and geometry is combined later in a worker. This listens for the
* render failure itself.
*/
test('drawing a polar box does not break the renderer', async ({ page }) => {
test.setTimeout(150_000);
await runAt(page, 89.99, 30);
await page.evaluate(() => {
/* eslint-disable @typescript-eslint/no-explicit-any */
const v: any = (window as any)._lsvMap;
(window as any).__renderErrors = [];
v.scene.renderError.addEventListener((_s: unknown, e: any) =>
(window as any).__renderErrors.push(String(e?.message ?? e)),
);
/* eslint-enable @typescript-eslint/no-explicit-any */
});
await page.waitForTimeout(6000);
const errors = await page.evaluate(
() => (window as never as { __renderErrors: string[] }).__renderErrors,
);
expect(errors).toEqual([]);
// Cesium swaps in an error panel when the render loop dies.
await expect(page.locator('.cesium-widget-errorPanel')).toHaveCount(0);
});
test('the panel reports a corridor-sized area at the pole, not a polar cap', async ({ page }) => {
test.setTimeout(150_000);
const panel = await runAt(page, 89.99, 30);
// Near a pole the four corners are unreadable on their own — a box whose north
// edge passes over the pole comes back down the far side — so the size line is
// what the operator actually checks. The lat/lon-rectangle form reported the
// whole cap north of 88.93, 44 200 km^2, for a corridor of about 1 700.
const size = panel.locator('.font-monospace', { hasText: 'km @' }).first();
await expect(size).toBeVisible();
const text = (await size.textContent()) ?? '';
const [w, h] = text.split('km @')[0].split('×').map((s) => parseFloat(s));
expect(w).toBeGreaterThan(0);
expect(h).toBeGreaterThan(0);
expect(w * h).toBeLessThan(10_000);
});