@saucelabs/cypress-visual-plugin
Version:
Cypress plugin for Sauce Visual Testing
216 lines (214 loc) • 7.06 kB
JavaScript
;
var __defProp = Object.defineProperty;
var __defProps = Object.defineProperties;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __propIsEnum = Object.prototype.propertyIsEnumerable;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __spreadValues = (a, b) => {
for (var prop in b || (b = {}))
if (__hasOwnProp.call(b, prop))
__defNormalProp(a, prop, b[prop]);
if (__getOwnPropSymbols)
for (var prop of __getOwnPropSymbols(b)) {
if (__propIsEnum.call(b, prop))
__defNormalProp(a, prop, b[prop]);
}
return a;
};
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
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 = {};
__export(commands_exports, {
getElementDimensions: () => getElementDimensions,
intoElement: () => intoElement,
isChainable: () => isChainable,
isRegion: () => isRegion,
toChainableRegion: () => toChainableRegion
});
module.exports = __toCommonJS(commands_exports);
var visualLog = (msg, level = "error") => cy.task("visual-log", { level, msg });
function isRegion(elem) {
if ("x" in elem && "y" in elem && "width" in elem && "height" in elem) {
return true;
}
return false;
}
function isChainable(elem) {
return "chainerId" in elem;
}
function intoElement(region) {
return "element" in region ? region.element : region;
}
function getElementDimensions(elem) {
const rect = elem.getBoundingClientRect();
return {
x: Math.floor(rect.left),
y: Math.floor(rect.top),
width: Math.floor(rect.width),
height: Math.floor(rect.height)
};
}
function toChainableRegion(item) {
if (isChainable(item)) {
return item.then(($el) => {
const result = [];
for (let i = 0; i < $el.length; i++)
result.push(getElementDimensions($el[i]));
return result;
});
} else if (isRegion(item)) {
return cy.wrap([item]);
} else {
return cy.wrap([]);
}
}
function chainableWaitForAll(list) {
const result = [];
list.forEach((item) => {
item.then((el) => {
result.push(el);
});
});
return cy.wrap(result);
}
var sauceVisualCheckCommand = (screenshotName, options) => {
var _a, _b;
const { clipSelector } = options != null ? options : {};
const randomId = () => Cypress._.random(0, 1e9);
cy.task("visual-log-capture", { screenshotName });
const viewport = {
width: 0,
height: 0
};
cy.window({ log: false }).then((win) => {
viewport.width = win.innerWidth;
viewport.height = win.innerHeight;
});
if (clipSelector) {
cy.get(clipSelector).then((elem) => {
const firstMatch = elem.get().find((item) => item);
if (firstMatch) {
cy.wrap(getElementDimensions(firstMatch)).as("clipToBounds");
}
});
} else {
cy.wrap(void 0).as("clipToBounds");
}
const visualRegions = [
...((_a = options == null ? void 0 : options.ignoredRegions) != null ? _a : []).map((r) => ({
enableOnly: [],
element: r
})),
...(_b = options == null ? void 0 : options.regions) != null ? _b : []
];
const resolved = chainableWaitForAll(
visualRegions.map(intoElement).map(toChainableRegion)
);
const regionsPromise = resolved.then((regions) => {
let hasError = false;
const result = [];
for (const idx in regions) {
if (regions[idx].length === 0) {
visualLog(
`sauce-visual: ignoreRegion[${idx}] does not exists or is empty`
);
hasError = true;
}
for (const plainRegion of regions[idx]) {
result.push(__spreadProps(__spreadValues({}, visualRegions[idx]), {
element: plainRegion
}));
}
}
if (hasError)
throw new Error(
"Some region are invalid. Please check the log for details."
);
return result;
});
const screenshotId = `sauce-visual-${randomId()}`;
cy.window({ log: false }).then((win) => {
cy.task("get-script", { log: false }).then((script) => {
const realViewport = viewport.height && viewport.width ? viewport : void 0;
const getDom = () => {
if (!(options == null ? void 0 : options.captureDom))
return null;
try {
if (!script)
throw new Error(`Cannot get dom capturing script.`);
const dom = win.eval(
`(function({ clipSelector }){${script}})({ clipSelector: '${clipSelector}' })`
);
if (typeof dom !== "string")
throw new Error(`Dom type should be a string not a ${typeof dom}.`);
return dom;
} catch (err) {
visualLog(`sauce-visual: Failed to capture dom:
${err}`);
return null;
}
};
return regionsPromise.then((regions) => {
var _a2;
cy.task("visual-register-screenshot", {
id: screenshotId,
name: screenshotName,
suiteName: Cypress.currentTest.titlePath.slice(0, -1).join(" "),
testName: Cypress.currentTest.title,
regions,
diffingMethod: options == null ? void 0 : options.diffingMethod,
diffingOptions: options == null ? void 0 : options.diffingOptions,
devicePixelRatio: win.devicePixelRatio,
viewport: realViewport,
dom: (_a2 = getDom()) != null ? _a2 : void 0
});
});
});
});
cy.get("@clipToBounds").then(
(clipToBounds) => {
cy.screenshot(screenshotId, __spreadValues({
clip: clipToBounds
}, options == null ? void 0 : options.cypress));
}
);
};
Cypress.Commands.add(
"visualCheck",
(screenshotName, options) => {
visualLog(
`sauce-visual: Command "visualCheck" is deprecated and will be removed in a future version. Please use "sauceVisualCheck".`,
"warn"
);
return sauceVisualCheckCommand(screenshotName, options);
}
);
Cypress.Commands.add("sauceVisualCheck", sauceVisualCheckCommand);
Cypress.Commands.add("sauceVisualResults", () => {
return cy.task("visual-test-results");
});
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
getElementDimensions,
intoElement,
isChainable,
isRegion,
toChainableRegion
});