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); });