Skip to content

Commit

Permalink
update broken links test to use linkinator
Browse files Browse the repository at this point in the history
  • Loading branch information
mm-jpoole committed Nov 16, 2023
1 parent 439730a commit 414044b
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 52 deletions.
83 changes: 40 additions & 43 deletions test/e2e/broken-links.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import blc from 'broken-link-checker';
// eslint-disable-next-line import/no-unresolved
import { LinkChecker, LinkResult } from 'linkinator';

const targetUrl = process.env.E2E_TARGET_URL || 'http://localhost:5000';

Expand All @@ -18,53 +19,49 @@ const falsePositives = [
'https://www.rubydoc.info/gems/minfraud/',
];

// eslint-disable-next-line compat/compat
const getBrokenLinks = (): Promise<any> => new Promise((resolve, reject) => {
try {
const brokenLinks: string[] = [];

const checker = new blc.SiteChecker({
excludedKeywords: [
...falsePositives,
],
honorRobotExclusions: false,
}, {
end: () => {
resolve(brokenLinks);
},
link: (result) => {
const { broken, http, url } = result;
const { statusCode } = http.response;
const { resolved: resolvedUrl } = url;
const getBrokenLinks = async () => {

// eslint-disable-next-line compat/compat
const { origin } = new URL(resolvedUrl);
const brokenLinks: LinkResult[] = [];

if (!broken) {
return;
}
const checker = new LinkChecker();

if (statusCode === 403 || statusCode === 429) {
return;
}
checker.on('link', (result) => {
const broken = result.state === 'BROKEN';
const statusCode = result.status ?? 0;
const resolvedUrl = result.url;
const { origin } = new URL(resolvedUrl);

if (
statusCode === 401
&& origin === 'https://www.maxmind.com'
) {
return;
}
if (!broken) {
return;
}

brokenLinks.push(result);
},
});
if (statusCode === 403 || statusCode === 429 || statusCode >= 500) {
return;
}

checker.enqueue(targetUrl, []);
} catch(err) {
reject(err);
}
});
if (statusCode === 401 && origin === 'https://www.maxmind.com') {
return;
}

test('website has no broken links', async () => {
expect(await getBrokenLinks()).toHaveNoBrokenLinks();
}, 1000 * 60 * 5);
brokenLinks.push(result);
});

await checker.check({
linksToSkip: falsePositives,
path: targetUrl,
recurse: true,
timeout: 30 * 1000,
});

return brokenLinks;

};

test(
'website has no broken links',
async () => {
expect(await getBrokenLinks()).toHaveNoBrokenLinks();
},
1000 * 60 * 5
);
31 changes: 22 additions & 9 deletions test/matchers/toHaveNoBrokenLinks.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,29 @@
import { matcherHint } from 'jest-matcher-utils';
// eslint-disable-next-line import/no-unresolved
import { LinkResult } from 'linkinator';

const BR = '\n';

const toHaveNoBrokenLinks = (brokenLinks: any[]): any => {
const isError = (err: Error | unknown): err is Error =>
err instanceof Error && 'message' in err && err.message !== undefined;

const formatedViolations = brokenLinks.map((brokenLink: any) => {
const list =
`Reason: ${brokenLink.brokenReason} ${BR}
Page: ${brokenLink.base.original} ${BR}
Broken Link Url: ${brokenLink.url.original} ${BR}
Broken Link Text: ${brokenLink.html.text} ${BR}
Broken Link Selector: ${brokenLink.html.selector} ${BR}`;
const toHaveNoBrokenLinks = (brokenLinks: LinkResult[]) => {
const formatedViolations = brokenLinks.map((brokenLink) => {
const reason = [
undefined,
0,
].includes(brokenLink.status)
? 'No response'
: `HTTP status ${brokenLink.status}`;

const failureDetails = brokenLink.failureDetails
?.map((err) => (isError(err) ? err.message : undefined))
.filter((err) => err !== undefined);

const list = `Reason: ${reason} ${BR}
Page: ${brokenLink.parent} ${BR}
Broken Link Url: ${brokenLink.url} ${BR}
Failure details: ${failureDetails?.join(BR)} ${BR}`;

return list;
});
Expand All @@ -33,7 +46,7 @@ const toHaveNoBrokenLinks = (brokenLinks: any[]): any => {
actual: brokenLinks,
message,
pass,
} as any;
};
};

expect.extend({
Expand Down

0 comments on commit 414044b

Please sign in to comment.