Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@jrpool/kilotest",
"version": "57.3.0",
"version": "58.0.0",
"description": "Ensemble testing for front-end web quality",
"type": "module",
"main": "index.ts",
Expand Down
11 changes: 10 additions & 1 deletion test/fixtures/buildFixtures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -203,11 +203,20 @@ const main = async () => {
const preventedCatalog = {
'0': catalogItem('IMG', 'An image', '/html/body/img[1]', '0:0:200:100')
};
// As in real reports, the prevented engine has a test act, with no standard result.
const preventedAlfaAct = {
type: 'test',
which: engineAlfa,
startTime: '26-01-01T00:00',
data: {prevented: true, error: 'page timed out'},
endTime: '26-01-01T00:01'
};
const preventedActs = [
testAct(engineAxe, [
instance('r11', 'The image has no alt text', 'failed',
issueLinkNoText, 0, 2, 1)
])
]),
preventedAlfaAct
];
const preventedReport = report('260101T0006-prv', 'Prevented Page',
'https://example.com/prevented', preventedActs, preventedCatalog);
Expand Down
10 changes: 10 additions & 0 deletions test/fixtures/db/reports/260101T0006-prv.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,16 @@
}
}
}
},
{
"type": "test",
"which": "alfa",
"startTime": "26-01-01T00:00",
"data": {
"prevented": true,
"error": "page timed out"
},
"endTime": "26-01-01T00:01"
}
],
"jobData": {
Expand Down
1 change: 1 addition & 0 deletions util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ export type AnnotatedAct = Act & {
// and the else/after-return branch is narrowed to UsableReport.
export type UsableReport = Omit<Report, 'target' | 'catalog' | 'jobData' | 'acts'> & {
error?: never;
id: string;
target: {what: string; url: string};
catalog: Catalog;
jobData: NonNullable<Report['jobData']> & {endTime: string; issuelessRules?: string[]};
Expand Down
25 changes: 6 additions & 19 deletions web/listDiagnoses/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,28 +14,15 @@
<main>
<h1><a href="/">Kilotest</a>: Diagnoses of <q>__issue__</q> violation by HTML element __catalogIndex__ on __target__ page</h1>
<h2>Basics</h2>
<h3>About the __target__ page</h3>
<ul>
<li>URL: __urlLink__</li>
<li>__testInfo__</li>
</ul>
<h3>About HTML element __catalogIndex__</h3>
<ul>
<li>Tag name: <code>__tagName__</code></li>
<li>Text: __text__</li>
<li>Start tag: <code>__startTag__</code></li>
<li>XPath: <code>__pathID__</code></li>
<li>Bounding box: __box__</li>
</ul>
<h3>About the page</h3>
__pageFacts__
<h3>About the issue</h3>
__issueFacts__
<h3>About the violator</h3>
__violatorFacts__
<ul class="nav">
__takeMeThere__
</ul>
<h3>About the <q>__issue__</q> issue</h3>
<ul>
<li>Why it matters: __why__</li>
<li>Priority: __priority__</li>
<li>Related WCAG standard: __wcag__</li>
</ul>
<h2>Diagnoses</h2>
<p>Here is how rule engines diagnose the <q>__issue__</q> issue for HTML element __catalogIndex__ of the __target__ page.</p>
<ol>
Expand Down
64 changes: 21 additions & 43 deletions web/listDiagnoses/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,12 @@ import {
ruleEngines
} from '../../util.ts';
import {
getIssueFactsLines,
getPageDataStrings,
getPageFactsLines,
getReportData,
getTextFragmentHref,
getWCAGLink,
getWeightName
getViolatorFactsLines
} from '../util.ts';
import {issues as issueSpecs} from 'testaro-issues';

Expand All @@ -32,48 +34,44 @@ const populateQuery = async (
pathID: string | null,
query: Record<string, any>
) => {
// Get descriptions of the page facts.
const pageDataStrings = await getPageDataStrings(timeStamp, jobID);
// Get the report.
const report = await getReport(timeStamp, jobID);
// If this failed:
if (pageDataStrings.error !== undefined) {
if (isReportError(report)) {
// Populate the query with the reason.
query.error = pageDataStrings.error;
query.error = report.error;
// Stop populating the query.
return;
}
const {testInfo, url, urlLink, description} = pageDataStrings;
// Otherwise, i.e. if it succeeded, get the report.
const report = await getReport(timeStamp, jobID);
// Otherwise, i.e. if it succeeded, get descriptions of the page facts.
const pageDataStrings = getPageDataStrings(report);
// If this failed:
if (isReportError(report)) {
if (pageDataStrings.error !== undefined) {
// Populate the query with the reason.
query.error = report.error;
query.error = pageDataStrings.error;
// Stop populating the query.
return;
}
const {testInfo, url, description} = pageDataStrings;
const {catalog} = report;
// Otherwise, i.e. if it succeeded, get the catalog item of the specified violator.
const catalogItem = catalog[catalogIndex];
const boxID = catalogItem?.boxID;
const startTag = catalogItem?.startTag;
const tagName = catalogItem?.tagName;
const text = catalogItem?.text;
query.catalogIndex = catalogIndex;
const lines: string[] = [];
const margin = ' '.repeat(6);
const catalogItem = catalog[catalogIndex];
// If the violator has a linkable text item, add a take-me-there link.
if (catalogIndex && catalogItem?.textLinkable) {
const href = getTextFragmentHref(text as string, url);
const href = getTextFragmentHref(catalogItem.text as string, url);
const label = `Take me to element ${catalogIndex} on the page (in a new tab)`;
const link = `<a href="${href}" target="_blank" aria-label="${label}">Take me there</a>`;
query.takeMeThere = `${margin} <p>${link}</p>`;
}
else {
query.takeMeThere = '';
}
// Add facts about the issue to the query.
// Add facts about the page to the query.
query.target = description;
query.urlLink = urlLink;
query.testInfo = testInfo;
query.pageFacts = getPageFactsLines(pageDataStrings, getReportData(report), margin).join('\n');
query.issue = issueSpecs[issueID]?.summary;
// If adding the issue summary failed:
if (!query.issue) {
Expand All @@ -82,29 +80,9 @@ const populateQuery = async (
// Stop populating the query.
return;
}
// Otherwise, i.e. if it succeeded, get the issue details.
const issue = issueSpecs[issueID]!;
const {wcag, weight, why} = issue;
query.why = why;
query.priority = getWeightName(weight);
query.wcag = `<a href="${getWCAGLink(wcag)}">${wcag}</a>`;
query.tagName = tagName || 'HTML';
if (text && !['HTML', 'BODY', 'HEAD', 'SCRIPT', 'STYLE', 'NOSCRIPT'].includes(tagName as string)) {
const textString = text.split('\n').join(' … ');
query.text = `<q>${htmlSafe(textString)}</q>`;
}
else {
query.text = '[not applicable]';
}
query.startTag = htmlSafe(startTag ?? '') || '[not obtained]';
query.pathID = pathID || '[not obtained]';
if (boxID) {
const dims = boxID.split(':');
query.box = `x = ${dims[0]}, y = ${dims[1]}, width = ${dims[2]}, height = ${dims[3]}`;
}
else {
query.box = '[not obtained]';
}
// Otherwise, i.e. if it succeeded, add the issue-facts and violator-facts lists to the query.
query.issueFacts = getIssueFactsLines(report, issueID, margin).join('\n');
query.violatorFacts = getViolatorFactsLines(report, issueID, catalogIndex, pathID, margin).join('\n');
// Initialize an array of diagnoses.
const diagnoses: any[] = [];
// For each violating standard instance that pertains to this combination of issue and violator:
Expand Down
16 changes: 14 additions & 2 deletions web/listDiagnoses/listDiagnoses.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ mock.module('../../util.ts', {
mock.module('../util.ts', {
exports: {
...realWebUtil,
getPageDataStrings: async (...args: any[]) => {
getPageDataStrings: (...args: any[]) => {
if (pageDataStringsOverride !== null) {
return pageDataStringsOverride;
}
Expand Down Expand Up @@ -108,7 +108,7 @@ test('listDiagnoses returns ok with no diagnoses for a nonexistent catalog index
assert.ok(!diagnosisTexts.some(t => t.includes('The link does not have an accessible name')));
});

test('listDiagnoses returns an error when getReport fails after getPageDataStrings succeeds', async () => {
test('listDiagnoses returns an error when getReport fails', async () => {
getReportCallCount = 0;
failGetReportOnCall = 1;
try {
Expand All @@ -121,6 +121,18 @@ test('listDiagnoses returns an error when getReport fails after getPageDataStrin
}
});

test('listDiagnoses returns an error when getPageDataStrings fails after getReport succeeds', async () => {
pageDataStringsOverride = {error: 'Page data strings error'};
try {
const result = await answer('linkNoText/260101T0000/mix/0');
assert.equal(result.status, 'error');
assert.equal(result.message, 'Page data strings error');
}
finally {
pageDataStringsOverride = null;
}
});

test('listDiagnoses includes a take-me-there link for a text-linkable catalog item', async () => {
const dbDir = (await import('../../test/dbFixture.ts')).fixtureDBDir;
const reportsDir = path.join(dbDir, 'reports');
Expand Down
14 changes: 2 additions & 12 deletions web/listIssues/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,10 @@
<body>
<main>
<h1><a href="/">Kilotest</a>: Issues reported for __target__</h1>
<h2>About the __target__ page</h2>
<ul>
<li>URL: __urlLink__</li>
<li>__testInfo__</li>
__preventions__
</ul>
<h2>About the page</h2>
__pageFacts__
<p><a href="/requestRetestForm.html/__timeStamp__/__jobID__">Should Kilotest retest the page?</a></p>
<h2>Issues reported</h2>
<h3>Summary</h3>
<p>__reporterCount__ reported issues (__reporters__)</p>
<p>__issueCount__ reported (__highestCount__ highest, __highCount__ high, __lowCount__ low, __lowestCount__ lowest priority)</p>
<p>__violatorCount__ reported</p>
<p>Download the <a href="/fullReport.json/__timeStamp__/__jobID__">full technical report</a></p>
<h3>Details</h3>
<details>
<summary>Highest priority: __highestCount__</summary>
<ul class="headed">
Expand Down
Loading
Loading