import { expect } from '@playwright/test'; import { test } from '../../fixtures/multi-client'; import { openSettingsFromMenu } from '../../helpers/app-menu'; import { expectDashboardReady } from '../../helpers/dashboard'; import { installTestServerEndpoints } from '../../helpers/seed-test-endpoint'; import { startTestServer } from '../../helpers/test-server'; import { readSignalServerCredentialFromPage, SIGNAL_SERVER_CREDENTIALS_STORAGE_KEY } from '../../helpers/auth-api'; import { RegisterPage } from '../../pages/register.page'; const PRIMARY_ENDPOINT_ID = 'e2e-offline-login-primary'; const USER_PASSWORD = 'TestPass123!'; test.describe('Offline signal server navigation', () => { test('does not redirect to authorize login after a foreign server goes offline', async ({ createClient }) => { const primaryServer = await startTestServer(); const secondaryServer = await startTestServer(); const suffix = `offline_login_${Date.now()}`; const username = `user_${suffix}`; try { const client = await createClient(); await installTestServerEndpoints(client.context, [ { id: PRIMARY_ENDPOINT_ID, name: 'E2E Primary Signal', url: primaryServer.url, isActive: true, status: 'online' } ]); await test.step('Register and provision a secondary signal server', async () => { const register = new RegisterPage(client.page); await register.goto(); await register.register(username, 'Offline Login User', USER_PASSWORD); await expectDashboardReady(client.page); await openSettingsFromMenu(client.page); await client.page.getByRole('button', { name: 'Network' }).click(); await client.page.getByPlaceholder('Server name').fill('E2E Secondary Signal'); await client.page.getByPlaceholder('Server URL (e.g., http://localhost:3001)').fill(secondaryServer.url); await client.page.getByTestId('add-signal-server-button').click(); await expect(client.page.getByText(secondaryServer.url)).toBeVisible({ timeout: 15_000 }); await expect.poll(async () => await readSignalServerCredentialFromPage(client.page, secondaryServer.url), { timeout: 30_000 } ).not.toBeNull(); await client.page.keyboard.press('Escape'); }); await test.step('Offline secondary endpoints do not trigger authorize login', async () => { await secondaryServer.stop(); await client.page.evaluate(({ storageKey, url }) => { const normalizedUrl = url.trim().replace(/\/+$/, ''); const credentialStore = JSON.parse(localStorage.getItem(storageKey) || '{}') as Record; const nextCredentialStore = Object.fromEntries( Object.entries(credentialStore).filter(([key]) => key !== normalizedUrl) ); localStorage.setItem(storageKey, JSON.stringify(nextCredentialStore)); const endpoints = JSON.parse(localStorage.getItem('metoyou_server_endpoints') || '[]') as { url: string; status: string; }[]; localStorage.setItem('metoyou_server_endpoints', JSON.stringify(endpoints.map((endpoint) => endpoint.url.trim().replace(/\/+$/, '') === normalizedUrl ? { ...endpoint, status: 'offline' } : endpoint ))); }, { storageKey: SIGNAL_SERVER_CREDENTIALS_STORAGE_KEY, url: secondaryServer.url }); await client.page.goto('/dashboard', { waitUntil: 'commit', timeout: 10_000 }); await expect(client.page).not.toHaveURL(/\/login/); await expect(client.page.url()).not.toMatch(/mode=authorize/); }); } finally { await primaryServer.stop(); await secondaryServer.stop(); } }); });