feat(globe): port to CeliumJS
This commit is contained in:
parent
ec03425067
commit
eb7698e034
51 changed files with 3521 additions and 1992 deletions
123
tests/e2e/bbox.spec.ts
Normal file
123
tests/e2e/bbox.spec.ts
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
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);
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue