feat(KAN-23): rebuild project overview and entry pages
This commit is contained in:
@@ -0,0 +1,167 @@
|
||||
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 base = 'http://127.0.0.1:4178';
|
||||
const context = await browser.newContext({
|
||||
viewport: { width: 1440, height: 1000 },
|
||||
});
|
||||
const page = await context.newPage();
|
||||
page.setDefaultTimeout(10000);
|
||||
const errors = [];
|
||||
page.on('pageerror', (error) => errors.push(error.message));
|
||||
const setRole = (value) =>
|
||||
context.addCookies([{ name: 'project_test_role', value, url: base }]);
|
||||
const content = () => page.locator('#main-content');
|
||||
const focusWithTab = async (link) => {
|
||||
await content().focus();
|
||||
for (let step = 0; step < 30; step++) {
|
||||
await page.keyboard.press('Tab');
|
||||
if (
|
||||
await link.evaluate((element) => element === document.activeElement)
|
||||
) {
|
||||
assert.equal(
|
||||
await link.evaluate((element) =>
|
||||
element.matches(':focus-visible'),
|
||||
),
|
||||
true,
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
assert.fail('Project action was not reachable by keyboard');
|
||||
};
|
||||
|
||||
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,
|
||||
reducedMotion: 'reduce',
|
||||
});
|
||||
await setRole('admin');
|
||||
for (const [path, title, label] of [
|
||||
['/projects', 'Projects', 'index'],
|
||||
[
|
||||
'/projects/7?template',
|
||||
'Engineering · Platform and developer experience',
|
||||
'hub',
|
||||
],
|
||||
['/projects?empty', 'Projects', 'empty'],
|
||||
]) {
|
||||
await page.goto(base + path);
|
||||
await page
|
||||
.getByRole('heading', {
|
||||
name: title,
|
||||
exact: true,
|
||||
level: 1,
|
||||
})
|
||||
.waitFor();
|
||||
await page.evaluate(() => document.fonts.ready);
|
||||
assert.equal(
|
||||
await page
|
||||
.locator('html')
|
||||
.evaluate((element) =>
|
||||
element.classList.contains('dark'),
|
||||
),
|
||||
theme === 'dark',
|
||||
);
|
||||
assert.equal(
|
||||
await page.evaluate(
|
||||
() =>
|
||||
document.documentElement.scrollWidth <=
|
||||
window.innerWidth,
|
||||
),
|
||||
true,
|
||||
`${label} overflows at ${width} in ${theme}`,
|
||||
);
|
||||
assert.equal(
|
||||
await content().locator('a a, a button').count(),
|
||||
0,
|
||||
);
|
||||
await page.screenshot({
|
||||
path: `/private/tmp/kan23-${label}-${width}-${theme}.png`,
|
||||
fullPage: true,
|
||||
});
|
||||
}
|
||||
await page.goto(`${base}/projects/7`);
|
||||
const board = content().getByRole('link', {
|
||||
name: 'Open board',
|
||||
exact: true,
|
||||
});
|
||||
await focusWithTab(board);
|
||||
await page.keyboard.press('Enter');
|
||||
await page.waitForURL('**/projects/7/board');
|
||||
await page
|
||||
.getByRole('heading', { name: 'Destination reached' })
|
||||
.waitFor();
|
||||
}
|
||||
}
|
||||
await setRole('reader');
|
||||
await page.goto(`${base}/projects`);
|
||||
assert.equal(
|
||||
await content()
|
||||
.getByRole('link', { name: 'New project', exact: true })
|
||||
.count(),
|
||||
0,
|
||||
);
|
||||
const overview = content().getByRole('link', {
|
||||
name: 'Open Engineering · Platform and developer experience overview',
|
||||
exact: true,
|
||||
});
|
||||
await focusWithTab(overview);
|
||||
await page.keyboard.press('Enter');
|
||||
await page.waitForURL('**/projects/7');
|
||||
assert.equal(
|
||||
await content()
|
||||
.locator(
|
||||
'a[href*="/settings/"], a[href$="/access"], a[href*="/templates/"]',
|
||||
)
|
||||
.count(),
|
||||
0,
|
||||
);
|
||||
await content()
|
||||
.getByRole('link', { name: 'Open backlog', exact: true })
|
||||
.click();
|
||||
await page.waitForURL('**/projects/7/backlog');
|
||||
|
||||
await setRole('admin');
|
||||
await page.goto(`${base}/projects/7`);
|
||||
const settings = content().getByRole('region', {
|
||||
name: 'Project settings',
|
||||
exact: true,
|
||||
});
|
||||
assert.equal(await settings.getByRole('link').count(), 6);
|
||||
const general = settings.getByRole('link', {
|
||||
name: 'General',
|
||||
exact: true,
|
||||
});
|
||||
await focusWithTab(general);
|
||||
await page.keyboard.press('Enter');
|
||||
await page.waitForURL('**/projects/7/settings/general');
|
||||
|
||||
await setRole('creator');
|
||||
await page.goto(`${base}/projects?empty`);
|
||||
const create = content().getByRole('link', {
|
||||
name: 'Create your first project',
|
||||
exact: true,
|
||||
});
|
||||
await focusWithTab(create);
|
||||
await page.keyboard.press('Enter');
|
||||
await page.waitForURL('**/projects/create');
|
||||
await page.goto(`${base}/projects/7`);
|
||||
await content()
|
||||
.getByRole('link', { name: 'Save as new template', exact: true })
|
||||
.click();
|
||||
await page.waitForURL('**/projects/7/templates/create');
|
||||
assert.deepEqual(errors, []);
|
||||
console.log(
|
||||
'Project overview browser checks passed: keyboard, navigation, permissions, empty states, 320/390/1440px and both themes.',
|
||||
);
|
||||
} finally {
|
||||
await browser.close();
|
||||
}
|
||||
Reference in New Issue
Block a user