Add user feature permissions and unified account management
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
const assert = require('node:assert/strict');
|
||||
const { chromium } = require(process.env.PLAYWRIGHT_PACKAGE || 'playwright');
|
||||
const base = process.env.REVIEW_BASE || 'http://localhost:3114';
|
||||
|
||||
(async () => {
|
||||
const browser = await chromium.launch();
|
||||
try {
|
||||
const context = await browser.newContext();
|
||||
await context.addCookies([{ name: 'magent_logged_in', value: '1', url: base }]);
|
||||
const all = { stats: true, requests: true, new_requests: true, issues: true, invites: true };
|
||||
const viewer = { id: 2, username: 'Georgia', role: 'user', email: 'georgia@example.test', features: { ...all }, stats: { total: 12, ready: 7, in_progress: 5 } };
|
||||
const other = { ...viewer, id: 3, username: 'Other viewer', features: { ...all, issues: false } };
|
||||
let signedIn = { username: 'Admin', role: 'admin', features: all };
|
||||
const writes = [];
|
||||
await context.route('**/api/**', async (route) => {
|
||||
const request = route.request(), path = new URL(request.url()).pathname;
|
||||
if (path === '/api/auth/me') return route.fulfill({ json: signedIn });
|
||||
if (request.method() === 'PUT' && path.includes('/features')) {
|
||||
writes.push({ path, payload: request.postDataJSON() });
|
||||
Object.assign(viewer.features, request.postDataJSON());
|
||||
return route.fulfill({ json: { updated: 2, features: viewer.features } });
|
||||
}
|
||||
if (path === '/api/admin/users/summary') return route.fulfill({ json: { users: [viewer, other] } });
|
||||
if (path === '/api/admin/users/id/2' || path === '/api/admin/users/Georgia') return route.fulfill({ json: { user: viewer, stats: viewer.stats } });
|
||||
if (path === '/api/admin/profiles') return route.fulfill({ json: { profiles: [] } });
|
||||
return route.fulfill({ json: {} });
|
||||
});
|
||||
const page = await context.newPage();
|
||||
const errors = []; page.on('pageerror', (error) => errors.push(error.message));
|
||||
for (const width of [1440, 390]) {
|
||||
await page.setViewportSize({ width, height: 1000 });
|
||||
await page.goto(`${base}/users/2`);
|
||||
await page.getByRole('heading', { name: 'Request statistics', exact: true }).waitFor();
|
||||
assert.equal(await page.getByRole('heading', { name: 'Access controls', exact: true }).count(), 0);
|
||||
const box = await page.locator('.user-detail-centered').boundingBox();
|
||||
assert(Math.abs(box.x + box.width / 2 - width / 2) < 4, 'Profile is centred');
|
||||
await page.getByRole('button', { name: 'Manage this user', exact: true }).click();
|
||||
const dialog = page.getByRole('dialog');
|
||||
await dialog.getByRole('checkbox', { name: /My Stats/ }).waitFor();
|
||||
assert(await dialog.evaluate((element) => element.scrollWidth <= element.clientWidth), `No modal overflow at ${width}`);
|
||||
assert.equal(await dialog.getByRole('checkbox').count(), 7);
|
||||
assert(await dialog.getByText('Restrict access or delete accounts', { exact: true }).count());
|
||||
await dialog.getByRole('checkbox', { name: /^Issues/ }).uncheck();
|
||||
await dialog.getByRole('button', { name: 'Save feature access', exact: true }).click();
|
||||
await dialog.getByRole('status').filter({ hasText: 'Feature access saved.' }).waitFor();
|
||||
assert.deepEqual(writes.at(-1).payload, { issues: false });
|
||||
await page.keyboard.press('Escape');
|
||||
await dialog.waitFor({ state: 'hidden' });
|
||||
assert(await page.getByRole('button', { name: 'Manage this user', exact: true }).evaluate((element) => element === document.activeElement));
|
||||
viewer.features.issues = true;
|
||||
}
|
||||
await page.goto(`${base}/users`);
|
||||
await page.getByRole('button', { name: 'Manage users', exact: true }).click();
|
||||
const dialog = page.getByRole('dialog');
|
||||
const issues = dialog.getByRole('checkbox', { name: /^Issues/ });
|
||||
await issues.waitFor();
|
||||
assert(await issues.evaluate((element) => element.indeterminate), 'Bulk mixed permissions shown');
|
||||
await issues.check();
|
||||
await dialog.getByRole('button', { name: 'Apply changed features to all users', exact: true }).click();
|
||||
await dialog.getByRole('status').filter({ hasText: 'Feature access saved for 2' }).waitFor();
|
||||
assert.deepEqual(writes.at(-1), { path: '/api/admin/users/features/bulk', payload: { issues: true } });
|
||||
signedIn = { username: 'Viewer', role: 'user', features: Object.fromEntries(Object.keys(all).map((key) => [key, false])) };
|
||||
for (const path of ['/insights', '/', '/new-requests', '/portal/issues', '/profile/invites']) {
|
||||
await page.goto(base + path);
|
||||
await page.getByRole('heading', { name: 'Feature unavailable' }).waitFor();
|
||||
assert.equal(await page.locator('.header-actions a, .workspace-mobile-nav a').count(), 0);
|
||||
}
|
||||
assert.deepEqual(errors, []);
|
||||
console.log('Passed: responsive centred profiles, management overlay, focus restoration, individual and mixed bulk permissions, saved payload scope, and all five denied routes/navigation. API traffic used fixtures only.');
|
||||
} finally { await browser.close(); }
|
||||
})().catch((error) => { console.error(error); process.exitCode = 1; });
|
||||
Reference in New Issue
Block a user