268 lines
10 KiB
JavaScript
268 lines
10 KiB
JavaScript
const {
|
|
start,
|
|
BASE: _BASE,
|
|
DIR,
|
|
assert,
|
|
fs,
|
|
path,
|
|
sanitized,
|
|
} = require('./portal-visual-qa-lib.cjs');
|
|
void (async () => {
|
|
const q = await start('next-accessibility-chromium-20261010');
|
|
let page, _ctx;
|
|
try {
|
|
({ page, ctx: _ctx } = await q.context('promoter'));
|
|
await q.login(page, 'promoter');
|
|
q.proof.pages = [];
|
|
const fixture = JSON.parse(
|
|
fs.readFileSync(
|
|
path.join(DIR, 'next-organization-chromium-20261010.json'),
|
|
'utf8',
|
|
),
|
|
).fixture;
|
|
for (const route of [
|
|
'/investidor/profile',
|
|
'/investidor/manifestacoes/' + fixture.new_submission,
|
|
'/minhas-oportunidades/36/edit',
|
|
'/minhas-oportunidades/51/resources',
|
|
'/parcerias/salas/1',
|
|
]) {
|
|
q.phase('Keyboard, accessible names and states ' + route);
|
|
await q.open(page, route);
|
|
await page.locator('main').first().waitFor();
|
|
await page.waitForLoadState('networkidle');
|
|
await page.addScriptTag({
|
|
path: path.join(DIR, 'qa-a11y-toolkit/package/axe.min.js'),
|
|
});
|
|
const result = await page.evaluate(async () => {
|
|
const r = await axe.run(document, {
|
|
runOnly: {
|
|
type: 'tag',
|
|
values: [
|
|
'wcag2a',
|
|
'wcag2aa',
|
|
'wcag21aa',
|
|
'best-practice',
|
|
],
|
|
},
|
|
});
|
|
return {
|
|
violations: r.violations.map((v) => ({
|
|
id: v.id,
|
|
impact: v.impact,
|
|
help: v.help,
|
|
nodes: v.nodes.map((n) => ({
|
|
target: n.target,
|
|
failureSummary: n.failureSummary,
|
|
})),
|
|
})),
|
|
incomplete: r.incomplete.map((v) => ({
|
|
id: v.id,
|
|
help: v.help,
|
|
nodes: v.nodes.map((n) => n.target),
|
|
})),
|
|
passes: r.passes.length,
|
|
};
|
|
});
|
|
const item = { route, ...result, keyboard: [] };
|
|
q.proof.pages.push(item);
|
|
if (route.startsWith('/investidor/manifestacoes/')) {
|
|
for (const name of [
|
|
'País de residência',
|
|
'País de constituição da entidade',
|
|
'País de origem declarado desta solicitação',
|
|
])
|
|
assert.equal(
|
|
await page
|
|
.getByRole('combobox', { name, exact: true })
|
|
.count(),
|
|
1,
|
|
);
|
|
assert.equal(
|
|
await page
|
|
.getByRole('combobox', {
|
|
name: 'País de constituição da entidade',
|
|
exact: true,
|
|
})
|
|
.inputValue(),
|
|
'FR',
|
|
);
|
|
assert(
|
|
await page
|
|
.getByText('Esta cópia conserva a origem', {
|
|
exact: false,
|
|
})
|
|
.isVisible(),
|
|
);
|
|
item.countries_named_and_source_shown = true;
|
|
}
|
|
q.save();
|
|
await page.evaluate(() => {
|
|
document.activeElement?.blur();
|
|
window.scrollTo(0, 0);
|
|
});
|
|
let skip = false;
|
|
for (let i = 0; i < 35; i++) {
|
|
await page.keyboard.press('Tab');
|
|
const focused = await page.evaluate(() => {
|
|
const e = document.activeElement,
|
|
s = getComputedStyle(e);
|
|
return {
|
|
tag: e.tagName,
|
|
id: e.id,
|
|
role: e.getAttribute('role'),
|
|
name:
|
|
e.getAttribute('aria-label') ||
|
|
e.textContent?.trim().slice(0, 100) ||
|
|
e.getAttribute('name'),
|
|
href: e.getAttribute('href'),
|
|
outline: {
|
|
style: s.outlineStyle,
|
|
width: s.outlineWidth,
|
|
color: s.outlineColor,
|
|
},
|
|
visible: e.getBoundingClientRect().height > 0,
|
|
};
|
|
});
|
|
item.keyboard.push(focused);
|
|
if (focused.href === '#portal-content') {
|
|
skip = true;
|
|
await q.shot(page, 'skip-' + q.proof.pages.length, false);
|
|
await page.keyboard.press('Enter');
|
|
assert(
|
|
await page
|
|
.locator('#portal-content')
|
|
.evaluate((e) => document.activeElement === e),
|
|
);
|
|
item.skip_reaches_content = true;
|
|
break;
|
|
}
|
|
}
|
|
assert(skip, 'Keyboard reaches skip link');
|
|
await page.keyboard.press('Tab');
|
|
item.after_skip = await page.evaluate(() => ({
|
|
tag: document.activeElement.tagName,
|
|
id: document.activeElement.id,
|
|
}));
|
|
const menu = page.getByRole('button', {
|
|
name: /Explorar investimentos/,
|
|
});
|
|
if (await menu.isVisible()) {
|
|
await menu.focus();
|
|
await page.keyboard.press('Enter');
|
|
assert.equal(await menu.getAttribute('aria-expanded'), 'true');
|
|
await page.keyboard.press('Escape');
|
|
assert.equal(await menu.getAttribute('aria-expanded'), 'false');
|
|
assert(
|
|
await menu.evaluate((e) => document.activeElement === e),
|
|
);
|
|
item.menu_keyboard_escape_returns_focus = true;
|
|
}
|
|
item.states = await page.getByRole('status').allTextContents();
|
|
item.alerts = await page.getByRole('alert').allTextContents();
|
|
if (route === '/parcerias/salas/1') {
|
|
await page
|
|
.getByRole('heading', {
|
|
name: 'Documentos autorizados',
|
|
exact: true,
|
|
})
|
|
.scrollIntoViewIfNeeded();
|
|
item.document_state = await page
|
|
.getByRole('status', {
|
|
name: 'Documentos disponíveis nesta sala',
|
|
exact: true,
|
|
})
|
|
.textContent();
|
|
}
|
|
if (route === '/investidor/profile') {
|
|
const box = page.getByRole('region', {
|
|
name: 'Cadastro mestre: Synthetic QA organization',
|
|
exact: true,
|
|
}),
|
|
country = box.getByRole('combobox', {
|
|
name: 'País de constituição da organização',
|
|
exact: true,
|
|
});
|
|
await country.selectOption('');
|
|
await box
|
|
.getByLabel('Fonte ou referência deste país', {
|
|
exact: true,
|
|
})
|
|
.fill('');
|
|
const wait = page.waitForResponse(
|
|
(r) =>
|
|
r.request().method() === 'PUT' &&
|
|
new URL(r.url()).pathname.endsWith('/country'),
|
|
);
|
|
await box
|
|
.getByRole('button', {
|
|
name: 'Guardar país no cadastro mestre',
|
|
exact: true,
|
|
})
|
|
.click();
|
|
assert([302, 303].includes((await wait).status()));
|
|
await page.waitForFunction(
|
|
() =>
|
|
document.activeElement?.getAttribute('aria-invalid') ===
|
|
'true',
|
|
);
|
|
assert(
|
|
await country.evaluate((e) => document.activeElement === e),
|
|
);
|
|
item.validation = await country.evaluate((e) => ({
|
|
invalid: e.getAttribute('aria-invalid'),
|
|
focused: document.activeElement === e,
|
|
error: document.getElementById(
|
|
e.getAttribute('aria-describedby'),
|
|
)?.textContent,
|
|
}));
|
|
assert(item.validation.error?.includes('país de constituição'));
|
|
assert.equal(await box.getByRole('alert').count(), 2);
|
|
await q.shot(page, 'master-error-focus', false);
|
|
}
|
|
await q.shot(page, 'keyboard-' + q.proof.pages.length, false);
|
|
q.save();
|
|
}
|
|
q.proof.checks = {
|
|
keyboard_and_skip_routes: q.proof.pages.every(
|
|
(p) => p.skip_reaches_content,
|
|
),
|
|
automated_violations: q.proof.pages.reduce(
|
|
(n, p) => n + p.violations.length,
|
|
0,
|
|
),
|
|
screen_reader_not_tested: true,
|
|
real_devices_not_tested: true,
|
|
};
|
|
q.proof.result = q.proof.checks.automated_violations
|
|
? 'violations_found'
|
|
: 'passed';
|
|
} catch (e) {
|
|
q.proof.result = 'failed';
|
|
q.proof.error = sanitized(e);
|
|
if (
|
|
page &&
|
|
!['/login', '/two-factor-challenge'].includes(
|
|
new URL(page.url()).pathname,
|
|
)
|
|
)
|
|
await q.shot(page, 'failure', false).catch(() => {});
|
|
} finally {
|
|
q.proof.completed_at = new Date().toISOString();
|
|
q.save();
|
|
await q.browser.close();
|
|
}
|
|
console.log(
|
|
JSON.stringify({
|
|
result: q.proof.result,
|
|
checks: q.proof.checks,
|
|
error: q.proof.error,
|
|
pages: q.proof.pages?.map((p) => ({
|
|
route: p.route,
|
|
violations: p.violations,
|
|
})),
|
|
}),
|
|
);
|
|
if (q.proof.result === 'failed') process.exitCode = 1;
|
|
})();
|