fix(web): simplify first-time token sign-in
This commit is contained in:
@@ -12,11 +12,29 @@ const { chromium } = await import(process.env.PLAYWRIGHT_MODULE || 'playwright-c
|
||||
const root = fileURLToPath(new URL('../dist/', import.meta.url));
|
||||
await readFile(resolve(root, 'sw.js'));
|
||||
const types = { '.html': 'text/html', '.js': 'text/javascript', '.css': 'text/css', '.json': 'application/json', '.webmanifest': 'application/manifest+json', '.png': 'image/png', '.ttf': 'font/ttf' };
|
||||
let sessionMode = 'token';
|
||||
const server = createServer(async (request, response) => {
|
||||
const path = new URL(request.url, 'http://localhost').pathname;
|
||||
if (path.startsWith('/api/')) {
|
||||
response.writeHead(401, { 'Content-Type': 'application/json', 'Cache-Control': 'no-store' });
|
||||
response.end(JSON.stringify({ error: true, message: 'missing bearer token', statusCode: 401 }));
|
||||
let status = 200;
|
||||
let body;
|
||||
if (sessionMode === 'unavailable') {
|
||||
status = 503;
|
||||
body = { message: 'Service temporarily unavailable' };
|
||||
} else if (sessionMode !== 'open' && request.headers.authorization !== 'Bearer local-login-fixture') {
|
||||
status = request.headers.authorization ? 403 : 401;
|
||||
body = { message: status === 401 ? 'missing bearer token' : 'invalid bearer token' };
|
||||
} else {
|
||||
body = {
|
||||
'/api/v1/auth/session': { authenticated: true, mode: sessionMode },
|
||||
'/api/v1/workspace-items': { items: [] },
|
||||
'/api/v1/models': { providers: {} },
|
||||
'/api/v1/chat-tools': { tools: [] },
|
||||
'/api/v1/active-runs': { chats: [], searches: [] },
|
||||
}[path] ?? {};
|
||||
}
|
||||
response.writeHead(status, { 'Content-Type': 'application/json', 'Cache-Control': 'no-store' });
|
||||
response.end(JSON.stringify(body));
|
||||
return;
|
||||
}
|
||||
const file = resolve(root, '.' + (path === '/' ? '/index.html' : path));
|
||||
@@ -40,14 +58,43 @@ try {
|
||||
// Activation must settle before a worker-controlled navigation can finish.
|
||||
await page.waitForFunction(() => navigator.serviceWorker.controller?.state === 'activated', undefined, { timeout: 15_000 });
|
||||
await page.getByPlaceholder('ADMIN_TOKEN').waitFor({ timeout: 5_000 });
|
||||
await page.getByPlaceholder('ADMIN_TOKEN').fill('local-login-fixture');
|
||||
assert.equal(await page.getByPlaceholder('ADMIN_TOKEN').inputValue(), 'local-login-fixture');
|
||||
assert.equal(await page.getByRole('alert').count(), 0);
|
||||
assert.equal(await page.getByRole('button', { name: 'Continue without token' }).count(), 0);
|
||||
assert.equal(await page.getByText(/If.*ADMIN_TOKEN/).count(), 0);
|
||||
assert.equal(await page.getByRole('button', { name: 'Sign in', exact: true }).isDisabled(), true);
|
||||
await page.getByPlaceholder('ADMIN_TOKEN').fill('incorrect-login-fixture');
|
||||
assert.equal(await page.getByRole('button', { name: 'Sign in', exact: true }).isEnabled(), true);
|
||||
await page.getByRole('button', { name: 'Sign in', exact: true }).click();
|
||||
await page.getByRole('alert').waitFor();
|
||||
assert.equal(await page.getByRole('alert').textContent(), 'Incorrect token. Please try again.');
|
||||
await page.reload({ waitUntil: 'domcontentloaded', timeout: 10_000 });
|
||||
await page.getByPlaceholder('ADMIN_TOKEN').waitFor({ timeout: 5_000 });
|
||||
assert.equal(await page.getByRole('alert').count(), 0);
|
||||
assert.equal(await page.evaluate(() => navigator.serviceWorker.controller?.state), 'activated');
|
||||
|
||||
// Invalid saved credentials are a real failure, unlike a first visit without credentials.
|
||||
await page.evaluate(() => localStorage.setItem('sybil_admin_token', 'outdated-login-fixture'));
|
||||
await page.reload({ waitUntil: 'domcontentloaded' });
|
||||
await page.getByRole('alert').waitFor();
|
||||
assert.equal(await page.getByRole('alert').textContent(), 'Incorrect token. Please try again.');
|
||||
await page.getByPlaceholder('ADMIN_TOKEN').fill('local-login-fixture');
|
||||
await page.getByRole('button', { name: 'Sign in', exact: true }).click();
|
||||
await page.locator('.workspace-shell').waitFor();
|
||||
assert.equal(await page.evaluate(() => localStorage.getItem('sybil_admin_token')), 'local-login-fixture');
|
||||
|
||||
await page.evaluate(() => localStorage.removeItem('sybil_admin_token'));
|
||||
sessionMode = 'open';
|
||||
await page.reload({ waitUntil: 'domcontentloaded' });
|
||||
await page.locator('.workspace-shell').waitFor();
|
||||
assert.equal(await page.getByPlaceholder('ADMIN_TOKEN').count(), 0);
|
||||
|
||||
// Suppress only the expected missing-token response, never connectivity/server failures.
|
||||
sessionMode = 'unavailable';
|
||||
await page.reload({ waitUntil: 'domcontentloaded' });
|
||||
await page.getByRole('alert').waitFor();
|
||||
assert.equal(await page.getByRole('alert').textContent(), 'Service temporarily unavailable');
|
||||
assert.deepEqual(errors, []);
|
||||
console.log('PASS first-visit service-worker activation, stable sign-in form, and controlled reload');
|
||||
console.log('PASS service-worker activation/reload, neutral first sign-in, rejected tokens, valid sign-in, automatic open-mode entry, and visible server failures');
|
||||
} finally {
|
||||
await browser.close();
|
||||
server.closeAllConnections();
|
||||
|
||||
Reference in New Issue
Block a user