UNPKG

cypress-html-validate

Version:

Cypress plugin for html-validate

245 lines (235 loc) 7.08 kB
"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/commands.ts var commands_exports = {}; module.exports = __toCommonJS(commands_exports); // src/utils/get-page-source.ts function getPageSource(document) { const matchCypress = new RegExp( /* eslint-disable-next-line sonarjs/slow-regex -- technical debt, could be refactored */ `(\\s*)<script type=["']text/javascript["']>.*?window.Cypress\\s*=\\s*parent.Cypress.*?</script>` ); const root = document.documentElement; return root.outerHTML.replace(matchCypress, (match, indent) => { return [ `${indent}<!-- [html-validate-disable-next no-unused-disable, require-sri, script-type] -->`, match ].join(""); }); } // src/utils/merge-options.ts function joinSelector(a, b) { return [a, b].join(" "); } function mergeOptions({ global, local = {}, subject }) { if (subject) { const merged = { ...global, ...{ include: [subject] } }; if (local.include) { merged.include = local.include.map((it) => joinSelector(subject, it)); } if (local.exclude) { merged.exclude = local.exclude.map((it) => joinSelector(subject, it)); } return merged; } else { return { ...global, ...local }; } } // src/get-arg.ts function getArg(is, ...args) { return args.find((it) => is(it)); } // src/filter/filter.ts function findElements(document, selectors) { return selectors.map((selector) => { return Array.from(document.querySelectorAll(selector)); }); } function matchSelectors(element, selector) { return selector.some((elements) => { return elements.some((inner) => inner.contains(element)); }); } var Filter = class { include; exclude; matchInclude; matchExclude; constructor(document, { include, exclude }) { this.include = findElements(document, include); this.exclude = findElements(document, exclude); this.matchInclude = include.length > 0; this.matchExclude = exclude.length > 0; } /** * Match element against filter. * * Returns `false` if the element matches: * * - none of include selectors * - one or more of exclude selectors * * Empty lists are not considered (in particular, if `include` is empty it is * the same as a selector to match the entire document). */ match(element) { const { exclude, include } = this; if (this.matchExclude && matchSelectors(element, exclude)) { return false; } if (this.matchInclude) { return matchSelectors(element, include); } return true; } }; // src/tasks/htmlvalidate.ts function taskHtmlvalidate(markup, config) { const options = { markup, config }; return cy.task("htmlvalidate", options, { log: false }); } // src/tasks/format.ts function taskFormat(messages) { return cy.task("htmlvalidate:format", messages, { log: false }); } // src/tasks/global-options.ts function taskGlobalOptions() { return cy.task("htmlvalidate:options", null, { log: false }); } // src/commands.ts function logError(error, $el) { Cypress.log({ $el, name: error.ruleId, consoleProps: () => error, message: [error.message] }); } function findElements2(messages, document) { return messages.map((message) => { return { ...message, element: message.selector ? document.querySelector(message.selector) : null }; }); } function filterMessages(messages, document, options) { const filter = new Filter(document, options); return messages.filter((message) => !message.element || filter.match(message.element)); } function omitElement(message) { const { element, ...rest } = message; return rest; } function isConfigData(src) { if (!src) { return false; } return "root" in src || "extends" in src || "elements" in src || "plugins" in src || "transform" in src || "rules" in src; } function isOptions(src) { if (!src) { return false; } return "exclude" in src || "include" in src || "formatter" in src; } function isJqueryWithSelector(subject) { return Boolean(subject && subject.selector); } function run(markup, config) { return taskHtmlvalidate(markup, config); } function getResults(document, config, options) { const source = getPageSource(document); return run(source, config).then((report) => { if (report.valid) { return cy.wrap([0, 0], { log: false }); } else { const messages = findElements2(report.results[0].messages, document); const filtered = filterMessages(messages, document, options); cy.wrap(filtered, { log: false }).each((error) => { const $el = error.element ? Cypress.$(error.element) : void 0; logError(error, $el); }); if (filtered.length > 0) { const stripped = filtered.map(omitElement); taskFormat(stripped); } return cy.wrap([messages.length, filtered.length], { log: false }); } }); } function validateResult([messages, filtered]) { const s = filtered !== 1 ? "s" : ""; const excluded = messages - filtered; assert.equal(filtered, 0, `${String(filtered)} error${s}, ${String(excluded)} excluded`); } function htmlvalidate(subject, arg1, arg2) { var _a, _b; const localConfig = (_a = getArg(isConfigData, arg1)) != null ? _a : {}; const localOptions = (_b = getArg(isOptions, arg2, arg1)) != null ? _b : {}; Cypress.log({ name: "html-validate", message: ["Validating document"] }); cy.document({ log: false }).then((document) => { taskGlobalOptions().then((globalOptions) => { if (isJqueryWithSelector(subject)) { const globalFilter = new Filter(document, globalOptions); const hidden = Array.from(subject).filter((it) => !globalFilter.match(it)); if (hidden.length > 0) { assert.fail(`Selected element is being excluded by global configuration`); } } const mergedOptions = mergeOptions({ global: globalOptions, local: localOptions, subject: isJqueryWithSelector(subject) ? subject.selector : void 0 }); Cypress.log({ name: "options", message: [mergedOptions.include, mergedOptions.exclude] }); return getResults(document, localConfig, mergedOptions); }).then((results) => { validateResult(results); }); }); } Cypress.Commands.add( "htmlvalidate", { prevSubject: "optional" }, htmlvalidate ); //# sourceMappingURL=commands.js.map