UNPKG

@sector-labs/seo-slip

Version:

Catches SEO regressions by sampling and checking a website against a set of rules

85 lines (72 loc) 2.71 kB
const { newMessage, newEmptyItemResult } = require('../reporting'); module.exports = (statusCodeRules) => { const name = 'statusCodeChecker'; const code = (statusCodeRules || {}).code || 200; const escapeRegExp = (string) => string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); const normalizeCode = (code) => (typeof code === 'number' ? [code] : code); const normalizeExceptions = (exceptions) => { // Output example: // [ // { regexp: /\/new-projects/, code: [ 301, 307 ] }, // { regexp: /\/ur\/new-projects/, code: [ 404 ] }, // ] return Object.keys(exceptions).map((key) => { const rule = exceptions[key]; if (typeof rule === 'object' && rule.regexp === true) { return { regexp: new RegExp(key), code: normalizeCode(rule.code), }; } return { regexp: RegExp(`^${escapeRegExp(key)}$`), code: normalizeCode(rule), }; }); }; const exceptions = normalizeExceptions((statusCodeRules || {}).exceptions || {}); const findException = (path, exceptions) => { return exceptions.find((exception) => path.match(exception.regexp)); }; return { analysis: (queueItem, responseBody, response) => { return { code: queueItem.stateData.code, path: queueItem.path, url: queueItem.url, referrer: queueItem.referrer, }; }, report: (analysis) => { return { code: analysis.code, path: analysis.path, }; }, check: (analysis) => { const result = newEmptyItemResult(); if (analysis.code === code) { return result; } const exception = findException(analysis.path, exceptions); if (exception) { if (exception.code.indexOf(analysis.code) === -1) { result.passed = false; result.messages.push( newMessage( analysis.url, name, `Expected code(s)=${exception.code}, actual=${analysis.code}` ) ); } return result; } result.passed = false; result.messages.push( newMessage(analysis.url, name, `Expected code(s)=${code}, actual=${analysis.code}`) ); return result; }, }; };