190 lines
7.1 KiB
JavaScript
190 lines
7.1 KiB
JavaScript
import assert from 'node:assert/strict';
|
|
import process from 'node:process';
|
|
const { chromium } = await import(
|
|
process.env.PLAYWRIGHT_MODULE ?? 'playwright'
|
|
);
|
|
const browser = await chromium.launch({ channel: 'chrome', headless: true });
|
|
const context = await browser.newContext({ reducedMotion: 'reduce' });
|
|
const page = await context.newPage();
|
|
page.setDefaultTimeout(10000);
|
|
const errors = [];
|
|
page.on('pageerror', (error) => errors.push(error.message));
|
|
const base = 'http://127.0.0.1:4198';
|
|
const result = (value) =>
|
|
context.addCookies([{ name: 'access_result', value, url: base }]);
|
|
const visit = async (query = '') => {
|
|
await result('success');
|
|
await page.goto(base + '/projects/1/access?reset' + query);
|
|
await page
|
|
.getByRole('heading', { name: 'Project access', exact: true })
|
|
.waitFor();
|
|
};
|
|
const button = (name) => page.getByRole('button', { name, exact: true });
|
|
const dialog = () => page.getByRole('dialog');
|
|
const checkbox = (name) =>
|
|
dialog().getByRole('checkbox', { name, exact: true });
|
|
const state = (value) =>
|
|
dialog()
|
|
.locator('[data-form-state="' + value + '"]')
|
|
.waitFor({ state: 'visible' });
|
|
const noOverflow = async () =>
|
|
assert.equal(
|
|
await page.evaluate(
|
|
() => document.documentElement.scrollWidth <= innerWidth,
|
|
),
|
|
true,
|
|
);
|
|
const save = async () => {
|
|
const request = page.waitForRequest((r) => r.method() === 'PATCH');
|
|
await dialog()
|
|
.getByRole('button', { name: 'Save permissions', exact: true })
|
|
.click();
|
|
return await request;
|
|
};
|
|
try {
|
|
for (const width of [1440, 390, 320]) {
|
|
await page.setViewportSize({ width, height: 1000 });
|
|
for (const theme of ['light', 'dark']) {
|
|
await page.emulateMedia({ colorScheme: theme });
|
|
await visit();
|
|
await noOverflow();
|
|
const trigger = button('Edit access for Sam Taylor');
|
|
await trigger.focus();
|
|
await page.keyboard.press('Enter');
|
|
await dialog().waitFor();
|
|
await noOverflow();
|
|
assert.equal(await checkbox('Read').isChecked(), true);
|
|
assert.equal(
|
|
await checkbox('Write').isChecked(),
|
|
false,
|
|
'Inherited write must not be editable as a direct grant',
|
|
);
|
|
await checkbox('Write').focus();
|
|
await page.keyboard.press('Space');
|
|
assert.equal(await checkbox('Write').isChecked(), true);
|
|
await page.keyboard.press('Space');
|
|
await page.keyboard.press('Tab');
|
|
assert.equal(
|
|
await dialog().evaluate((el) =>
|
|
el.contains(document.activeElement),
|
|
),
|
|
true,
|
|
);
|
|
await page.screenshot({
|
|
path:
|
|
'/private/tmp/kan48-dialog-' + width + '-' + theme + '.png',
|
|
});
|
|
await page.keyboard.press('Escape');
|
|
await dialog().waitFor({ state: 'hidden' });
|
|
assert.equal(
|
|
await trigger.evaluate((el) => el === document.activeElement),
|
|
true,
|
|
);
|
|
await page.screenshot({
|
|
path: '/private/tmp/kan48-' + width + '-' + theme + '.png',
|
|
fullPage: true,
|
|
});
|
|
}
|
|
}
|
|
await page.locator('#access-search').fill('SAM@EXAMPLE');
|
|
assert.equal(await page.locator('[data-user-id]').count(), 1);
|
|
await page.getByText('No matching teams', { exact: true }).waitFor();
|
|
await page.locator('#access-search').fill('unmatched');
|
|
await page.getByText('No matching people', { exact: true }).waitFor();
|
|
await visit('&empty&noUsers');
|
|
await page.getByText('No teams yet', { exact: true }).waitFor();
|
|
await page.getByText('No people available', { exact: true }).waitFor();
|
|
await visit();
|
|
await button('Edit access for Alex Morgan').click();
|
|
await dialog()
|
|
.getByText('This person is a global administrator.', { exact: false })
|
|
.waitFor();
|
|
await page.keyboard.press('Escape');
|
|
await button('Edit access for Sam Taylor').click();
|
|
await checkbox('Read').uncheck();
|
|
const request = await save();
|
|
assert.equal(
|
|
new URL(request.url()).pathname,
|
|
'/projects/1/permissions/users/2',
|
|
);
|
|
assert.deepEqual(request.postDataJSON(), { permissions: [] });
|
|
await dialog().waitFor({ state: 'hidden' });
|
|
await page
|
|
.locator('[data-user-id="2"]')
|
|
.getByText('Write', { exact: true })
|
|
.first()
|
|
.waitFor();
|
|
await button('Edit access for Sam Taylor').click();
|
|
assert.equal(await checkbox('Read').isChecked(), false);
|
|
await page.keyboard.press('Escape');
|
|
await button('Edit access for Platform team').click();
|
|
await checkbox('Write').uncheck();
|
|
await save();
|
|
await dialog().waitFor({ state: 'hidden' });
|
|
await page
|
|
.locator('[data-user-id="2"]')
|
|
.getByText('No project access', { exact: true })
|
|
.waitFor();
|
|
|
|
await button('Edit access for Sam Taylor').click();
|
|
await checkbox('Administrator').check();
|
|
await result('validation');
|
|
await save();
|
|
await state('validation');
|
|
await dialog()
|
|
.getByText('This permission is unavailable.', { exact: true })
|
|
.waitFor();
|
|
assert.equal(await checkbox('Administrator').isChecked(), true);
|
|
assert.equal(
|
|
await dialog().locator('fieldset').getAttribute('aria-invalid'),
|
|
'true',
|
|
);
|
|
await result('server');
|
|
await save();
|
|
await state('server');
|
|
await result('success');
|
|
await page.route('**/permissions/users/2', (route) =>
|
|
route.abort('failed'),
|
|
);
|
|
await save();
|
|
await state('network');
|
|
await page.unroute('**/permissions/users/2');
|
|
await dialog()
|
|
.getByRole('button', { name: 'Try again', exact: true })
|
|
.click();
|
|
await dialog().waitFor({ state: 'hidden' });
|
|
await page
|
|
.locator('[data-user-id="2"]')
|
|
.getByText('Administrator', { exact: true })
|
|
.first()
|
|
.waitFor();
|
|
await button('Edit access for Sam Taylor').click();
|
|
assert.equal(await checkbox('Administrator').isChecked(), true);
|
|
await result('forbidden');
|
|
await save();
|
|
await state('server');
|
|
await dialog()
|
|
.getByText('Project access can no longer be changed', { exact: true })
|
|
.waitFor();
|
|
assert.equal(
|
|
await dialog().getByRole('button', { name: 'Try again' }).count(),
|
|
0,
|
|
);
|
|
await page.keyboard.press('Escape');
|
|
await visit();
|
|
await button('Edit access for Sam Taylor').click();
|
|
await checkbox('Write').check();
|
|
page.once('dialog', (d) => d.dismiss());
|
|
await page.keyboard.press('Escape');
|
|
assert.equal(await dialog().isVisible(), true);
|
|
page.once('dialog', (d) => d.accept());
|
|
await page.keyboard.press('Escape');
|
|
await dialog().waitFor({ state: 'hidden' });
|
|
assert.deepEqual(errors, []);
|
|
console.log(
|
|
'Project access browser checks passed: direct/team updates and clearing, effective access refresh, errors/retry, unsaved changes, keyboard, 320/390/1440px, both themes.',
|
|
);
|
|
} finally {
|
|
await browser.close();
|
|
}
|