test(e2e): role-shadowing specs in apps + scripts suites
Lifts loginAsUserToken + pageWithUserToken out of members.spec.ts into fixtures/role-page.ts (third file that needs them). Adds shadowing coverage: viewer member sees no New-app / Add-domain / Settings / Save / +Add-route, editor sees Save but no Delete header, and CodeMirror renders contenteditable=false for viewers. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
46
dashboard/tests/e2e/fixtures/role-page.ts
Normal file
46
dashboard/tests/e2e/fixtures/role-page.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
// Helpers for tests that drive the dashboard as a non-bootstrap admin
|
||||
// (member with an app-membership row, custom InstanceRole, etc.).
|
||||
//
|
||||
// `loginAsUserToken` exchanges username/password for a bearer token
|
||||
// via the admin API. `pageWithUserToken` opens a fresh browser
|
||||
// context, seeds the dashboard's localStorage entry, and returns the
|
||||
// page ready to navigate. Callers are responsible for closing the
|
||||
// returned page's context.
|
||||
|
||||
import { expect, request, type Browser, type Page } from '@playwright/test';
|
||||
|
||||
const API_BASE = process.env.E2E_API_BASE ?? 'http://127.0.0.1:18080';
|
||||
|
||||
export async function loginAsUserToken(
|
||||
username: string,
|
||||
password: string
|
||||
): Promise<string> {
|
||||
const probe = await request.newContext({ baseURL: API_BASE });
|
||||
try {
|
||||
const res = await probe.post('/api/v1/admin/auth/login', {
|
||||
data: { username, password },
|
||||
headers: { 'content-type': 'application/json' }
|
||||
});
|
||||
expect(res.ok()).toBe(true);
|
||||
return ((await res.json()) as { token: string }).token;
|
||||
} finally {
|
||||
await probe.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
export async function pageWithUserToken(
|
||||
browser: Browser,
|
||||
token: string
|
||||
): Promise<Page> {
|
||||
const ctx = await browser.newContext({ storageState: undefined });
|
||||
const page = await ctx.newPage();
|
||||
// Seed localStorage on the right origin, then navigate normally.
|
||||
await page.goto('/admin/login');
|
||||
await page.evaluate(
|
||||
([key, value]) => {
|
||||
localStorage.setItem(key, value);
|
||||
},
|
||||
['picloud.admin.token', token]
|
||||
);
|
||||
return page;
|
||||
}
|
||||
Reference in New Issue
Block a user