Skip authorize login navigation when a signal server endpoint is offline or unreachable; gate connection and credential flows on online status only. Co-authored-by: Cursor <cursoragent@cursor.com>
89 lines
3.7 KiB
TypeScript
89 lines
3.7 KiB
TypeScript
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<string, unknown>;
|
|
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();
|
|
}
|
|
});
|
|
});
|