test: size in the appearance end-to-end check (T7)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+23
-19
@@ -26,10 +26,10 @@ async function login(user, password = 'password123', setup) {
|
||||
return page;
|
||||
}
|
||||
|
||||
// The <html> attributes theme.js sets; absent means the built-in default (auto, standard, purple).
|
||||
// The <html> attributes theme.js sets; absent means the built-in default (auto, standard, normal, purple).
|
||||
const looks = (page) => page.evaluate(() => {
|
||||
const d = document.documentElement.dataset;
|
||||
return `${d.mode ?? 'auto'} ${d.contrast ?? 'standard'} ${d.palette ?? 'purple'}`;
|
||||
return `${d.mode ?? 'auto'} ${d.contrast ?? 'standard'} ${d.size ?? 'normal'} ${d.palette ?? 'purple'}`;
|
||||
});
|
||||
|
||||
async function expectLook(name, page, want) {
|
||||
@@ -78,8 +78,8 @@ await Promise.all(['jdoe', 'msmith', 'pweber'].map(resetUser));
|
||||
// 1. Admin default on the Display settings tab
|
||||
const admin = await login('admin', 'admin');
|
||||
await admin.goto(`${BASE}/settings?tab=display`);
|
||||
// Mode, contrast and color are three form rows
|
||||
const rowsShown = () => admin.$$eval('p:has([data-nm-default])', (rows) => rows.length === 3 && rows.map((r) => !!r.offsetParent));
|
||||
// Mode, contrast, size and color are four form rows
|
||||
const rowsShown = () => admin.$$eval('p:has([data-nm-default])', (rows) => rows.length === 4 && rows.map((r) => !!r.offsetParent));
|
||||
check('default picker shown while Tonalmine is selected', (await rowsShown())?.every(Boolean));
|
||||
await admin.selectOption('#settings_ui_theme', '');
|
||||
check('default picker hidden and not posted for another theme', (await rowsShown())?.every((shown) => !shown) &&
|
||||
@@ -94,25 +94,29 @@ check('default picker shows the saved default', await admin.evaluate(() =>
|
||||
|
||||
// 2. A user without a choice gets the default
|
||||
const jdoe = await login('jdoe');
|
||||
await expectLook('user without a choice gets the default', jdoe, 'dark standard blue');
|
||||
await expectLook('user without a choice gets the default', jdoe, 'dark standard normal blue');
|
||||
|
||||
// 3. The user's choice is saved on the account and only overrides that part
|
||||
check('choosing Light is saved (204)', (await pick(jdoe, '[data-nm-mode="light"]')) === 204);
|
||||
check('choosing Compact is saved (204)', (await pick(jdoe, '[data-nm-size="compact"]')) === 204);
|
||||
const jdoe2 = await login('jdoe');
|
||||
await expectLook('choice follows the user to another browser', jdoe2, 'light standard blue');
|
||||
await expectLook('choice follows the user to another browser', jdoe2, 'light standard compact blue');
|
||||
|
||||
// 4. Parts the user didn't change follow a new default
|
||||
await saveDefault(admin, () => admin.click('[data-nm-default] [data-nm-palette="green"]'));
|
||||
// 4. Parts the user didn't change follow a new default; the user's Compact beats the default Large
|
||||
await saveDefault(admin, async () => {
|
||||
await admin.click('[data-nm-default] [data-nm-palette="green"]');
|
||||
await admin.click('[data-nm-default] [data-nm-size="large"]');
|
||||
});
|
||||
await jdoe2.reload({ waitUntil: 'networkidle' });
|
||||
await expectLook('unchanged parts follow the new default', jdoe2, 'light standard green');
|
||||
await expectLook('unchanged parts follow the new default', jdoe2, 'light standard compact green');
|
||||
|
||||
// 5. Reset to default
|
||||
check('Reset to default is shown after a change', await jdoe2.isVisible('#account [data-nm-reset]') ||
|
||||
await jdoe2.evaluate(() => !document.querySelector('#account [data-nm-reset]').hidden));
|
||||
check('reset is saved (204)', (await pick(jdoe2, '[data-nm-reset]')) === 204);
|
||||
await expectLook('reset returns to the default', jdoe2, 'dark standard green');
|
||||
await expectLook('reset returns to the default', jdoe2, 'dark standard large green');
|
||||
await jdoe2.reload({ waitUntil: 'networkidle' });
|
||||
await expectLook('reset is kept after reload', jdoe2, 'dark standard green');
|
||||
await expectLook('reset is kept after reload', jdoe2, 'dark standard large green');
|
||||
check('Reset to default is hidden without a choice', await jdoe2.evaluate(() => document.querySelector('#account [data-nm-reset]').hidden));
|
||||
|
||||
// 5b. A custom color, with its generated CSS, is saved on the account
|
||||
@@ -120,33 +124,33 @@ const savedColor = jdoe2.waitForResponse((r) => r.url().includes('/tonalmine/app
|
||||
await pickColor(jdoe2, '#account', '#c0392b');
|
||||
check('custom color is saved (204)', (await savedColor).status() === 204);
|
||||
const jdoe3 = await login('jdoe');
|
||||
await expectLook('custom color follows the user', jdoe3, 'dark standard custom');
|
||||
await expectLook('custom color follows the user', jdoe3, 'dark standard large custom');
|
||||
check('custom color CSS comes from the account', (await customCss(jdoe3)) > 1000);
|
||||
await pick(jdoe3, '[data-nm-reset]');
|
||||
|
||||
// 6. A localStorage choice from before the plugin moves to the account once
|
||||
const msmith = await login('msmith', 'password123', () => localStorage.setItem('tonalmine', '{"contrast":"high"}'));
|
||||
await expectLook('localStorage choice is applied after login', msmith, 'dark high green');
|
||||
await expectLook('localStorage choice is applied after login', msmith, 'dark high large green');
|
||||
check('localStorage is cleared for logged-in users', await msmith.evaluate(() => localStorage.getItem('tonalmine') === null));
|
||||
const msmith2 = await login('msmith');
|
||||
await expectLook('uploaded choice is on the account', msmith2, 'dark high green');
|
||||
await expectLook('uploaded choice is on the account', msmith2, 'dark high large green');
|
||||
|
||||
// 7. Validation; the request without a CSRF token goes last, since Redmine then ends the session
|
||||
const pweber = await login('pweber');
|
||||
check('valid choice is saved (204)', (await put(pweber, { contrast: 'medium' })) === 204);
|
||||
for (const body of [{ mode: 'neon' }, { palette: 'custom' }, { palette: 'custom', seed: '#123456', css: '</style>' }, { foo: 1 }, { mode: 5 }]) {
|
||||
for (const body of [{ mode: 'neon' }, { palette: 'custom' }, { palette: 'custom', seed: '#123456', css: '</style>' }, { size: 'huge' }, { foo: 1 }, { mode: 5 }]) {
|
||||
const status = await put(pweber, body);
|
||||
check(`invalid ${JSON.stringify(body)} is refused (422)`, status === 422, `got ${status}`);
|
||||
}
|
||||
const tokenless = await put(pweber, { contrast: 'high' }, false);
|
||||
check('request without CSRF token is refused (422)', tokenless === 422, `got ${tokenless}`);
|
||||
const pweber2 = await login('pweber');
|
||||
await expectLook('refused requests left the choice unchanged', pweber2, 'dark medium green');
|
||||
await expectLook('refused requests left the choice unchanged', pweber2, 'dark medium large green');
|
||||
|
||||
// 8. Anonymous visitors get the default
|
||||
const anonymous = await (await browser.newContext()).newPage();
|
||||
await anonymous.goto(`${BASE}/login`);
|
||||
await expectLook('anonymous visitor gets the default', anonymous, 'dark standard green');
|
||||
await expectLook('anonymous visitor gets the default', anonymous, 'dark standard large green');
|
||||
|
||||
// 8b. A custom default color reaches everyone
|
||||
await saveDefault(admin, async () => {
|
||||
@@ -154,13 +158,13 @@ await saveDefault(admin, async () => {
|
||||
await admin.waitForFunction(() => document.querySelector('[data-nm-default-input="css"]').value.length > 1000);
|
||||
});
|
||||
await anonymous.reload();
|
||||
await expectLook('custom default reaches anonymous visitors', anonymous, 'dark standard custom');
|
||||
await expectLook('custom default reaches anonymous visitors', anonymous, 'dark standard large custom');
|
||||
check('custom default CSS is rendered', (await customCss(anonymous)) > 1000);
|
||||
|
||||
// 9. Clean up: empty default, so other checks and screenshots see the built-in look
|
||||
await saveDefault(admin, () => admin.$$eval('[data-nm-default-input]', (inputs) => inputs.forEach((i) => { i.value = ''; })));
|
||||
await anonymous.reload();
|
||||
await expectLook('empty default restores the built-in look', anonymous, 'auto standard purple');
|
||||
await expectLook('empty default restores the built-in look', anonymous, 'auto standard normal purple');
|
||||
await Promise.all(['jdoe', 'msmith', 'pweber'].map(resetUser));
|
||||
|
||||
await browser.close();
|
||||
|
||||
Reference in New Issue
Block a user