cypress-html-validate
Version:
Cypress plugin for html-validate
245 lines (235 loc) • 7.08 kB
JavaScript
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
;