61 lines
2.5 KiB
TypeScript
61 lines
2.5 KiB
TypeScript
import { test, expect, type Page } from '@playwright/test';
|
|
|
|
const SAT_ID = '550e8400-e29b-41d4-a716-446655440000';
|
|
|
|
async function login(page: Page) {
|
|
await page.goto('/login/');
|
|
await page.fill('#lg-username', 'demo');
|
|
await page.fill('#lg-password', 'demo');
|
|
await page.click('button[type=submit]');
|
|
await expect(page.getByTestId('nav-menu')).toBeVisible();
|
|
}
|
|
|
|
test('an invalid satellite id is rejected before connecting', async ({ page }) => {
|
|
await login(page);
|
|
// Tracking is its own mode now, reached from the header.
|
|
await page.getByTestId('mode-track').click();
|
|
await page.getByTestId('tr-advanced').locator('summary').click();
|
|
await page.getByTestId('tr-id').fill('not-a-uuid');
|
|
await page.getByTestId('tr-connect').click();
|
|
await expect(page.getByTestId('tr-error')).toBeVisible();
|
|
await expect(page.getByTestId('tr-status')).toContainText(/ошибка|error/i);
|
|
});
|
|
|
|
test('following a satellite loads history, goes live, and draws the track', async ({ page }) => {
|
|
await login(page);
|
|
// Tracking is its own mode now, reached from the header.
|
|
await page.getByTestId('mode-track').click();
|
|
await page.getByTestId('tr-advanced').locator('summary').click();
|
|
await page.getByTestId('tr-id').fill(SAT_ID);
|
|
await page.getByTestId('tr-connect').click();
|
|
|
|
// History (20 packets) arrives over REST, then the socket reports "live".
|
|
await expect(page.getByTestId('tr-status')).toContainText(/на связи|live/i, { timeout: 15000 });
|
|
await expect(page.getByTestId('tr-readout')).toBeVisible();
|
|
|
|
// Returns 0 until the map's style has loaded, so the polls below just wait.
|
|
const trackLayerCount = () =>
|
|
page.evaluate(() => {
|
|
const map = (window as unknown as { _sfMap?: { getStyle(): { layers: { id: string }[] } } })
|
|
._sfMap;
|
|
if (!map) return 0;
|
|
return map
|
|
.getStyle()
|
|
.layers.map((l) => l.id)
|
|
.filter((id) => id.startsWith('telemetry__')).length;
|
|
});
|
|
|
|
// The actual track is drawn in its own scene (line + current-position marker).
|
|
await expect.poll(trackLayerCount).toBeGreaterThan(0);
|
|
|
|
// Live packets keep arriving over the WebSocket (~1/s), extending the track.
|
|
const before = await page.getByTestId('tr-readout').innerText();
|
|
await expect
|
|
.poll(async () => page.getByTestId('tr-readout').innerText(), { timeout: 15000 })
|
|
.not.toBe(before);
|
|
|
|
// Disconnecting clears the track and returns to the idle state.
|
|
await page.getByTestId('tr-disconnect').click();
|
|
await expect(page.getByTestId('tr-status')).toContainText(/не подключено|not connected/i);
|
|
await expect.poll(trackLayerCount).toBe(0);
|
|
});
|