test-real-styles
Version:
utilities to test real styling of dom elements
359 lines (346 loc) • 11 kB
JavaScript
;
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
var __getProtoOf = Object.getPrototypeOf;
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 __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 __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var __async = (__this, __arguments, generator) => {
return new Promise((resolve, reject) => {
var fulfilled = (value) => {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
};
var rejected = (value) => {
try {
step(generator.throw(value));
} catch (e) {
reject(e);
}
};
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
step((generator = generator.apply(__this, __arguments)).next());
});
};
// src/index.ts
var src_exports = {};
__export(src_exports, {
PLAYWRIGHT_BROWSERS: () => PLAYWRIGHT_BROWSERS,
cleanup: () => cleanup,
getRealStyles: () => getRealStyles,
launch: () => launchPage,
normalizeValue: () => normalize,
toCss: () => toCss
});
module.exports = __toCommonJS(src_exports);
// src/launch.ts
var import_playwright = __toESM(require("playwright"), 1);
// src/resolveStyleInput.ts
function resolveStyleInput(stylesP) {
return __async(this, null, function* () {
const styles = yield stylesP;
if (typeof styles !== "string") {
return styles;
}
if (styles.match(/^http/)) {
return { url: styles };
} else if (styles.match(/\{/)) {
return { content: styles };
}
return { path: styles };
});
}
// src/launch.ts
var import_dom_to_playwright = __toESM(require("dom-to-playwright"), 1);
// src/getStyles.ts
var import_lodash = __toESM(require("lodash.kebabcase"), 1);
// src/normalize.ts
var import_rgb_hex = __toESM(require("rgb-hex"), 1);
var import_color_namer = __toESM(require("color-namer"), 1);
function normalize(value) {
return value.replace(/rgb\([0-9, ]+\)/gi, (match) => {
return `#${(0, import_rgb_hex.default)(match)}`;
}).replace(
/(#([0-9a-f]{6}|[0-9a-f]{3}))([^0-9a-f]|$)/gi,
(_, hex, __, delm) => {
const namedColor = (0, import_color_namer.default)(hex).html[0];
return `${(namedColor.distance === 0 ? namedColor.name : hex).toLowerCase()}${delm}`;
}
);
}
// src/extractStyles.ts
function extractStyles(element, { styles, pseudoElt }) {
const computed = window.getComputedStyle(element, pseudoElt);
return styles.reduce((memo, { key, name }) => {
memo[name] = computed.getPropertyValue(key);
return memo;
}, {});
}
// src/getStyles.ts
function getStyles(_0, _1, _2) {
return __async(this, arguments, function* (page, selector, props, { normalize: normalize2 = normalize, pseudoElt } = {}) {
const styles = props.map((prop) => {
if (typeof prop !== "string") {
throw new Error(`Unexpected prop ${prop} of type ${typeof prop}`);
}
return {
name: prop,
key: (0, import_lodash.default)(prop).toLowerCase()
};
});
const computedStyles = yield page.$eval(selector, extractStyles, {
styles,
pseudoElt
});
return Object.keys(computedStyles).reduce((memo, key) => {
memo[key] = normalize2(computedStyles[key], key);
return memo;
}, {});
});
}
// src/withTimeout.ts
function withTimeout(promisedValue, message = "Timed out after %n", timeout = 1e4) {
return Promise.race([
promisedValue,
new Promise(
(_, rej) => setTimeout(
() => rej(
new Error(
message.replace(
"%n",
timeout >= 1e3 ? `${Math.round(timeout / 1e3)}s` : `${timeout}ms`
)
)
),
timeout
)
)
]);
}
// src/launch.ts
var import_ichschwoer = require("ichschwoer");
var domToPlaywright = (
/* @ts-ignore */
import_dom_to_playwright.default.__esModule ? (
/* @ts-ignore */
import_dom_to_playwright.default.default
) : import_dom_to_playwright.default
);
if (!global.setImmediate) {
global.setImmediate = setTimeout;
}
var PLAYWRIGHT_BROWSERS = [
"chromium",
"firefox",
"webkit"
];
var cache = {};
var DISABLE_TRANSITIONS = `
* {
-moz-transition: none !important;
-webkit-transition: none !important;
transition: none !important;
}`;
function launchPage(browserName, stylesInput) {
if (!cache[browserName]) {
cache[browserName] = withTimeout(
import_playwright.default[browserName].launch(),
`Failed to launch ${browserName} in under %n`
);
}
const browserP = cache[browserName];
const contextP = withTimeout(
browserP.then((b) => b.newContext()),
`Failed to create context in ${browserName} in under %n`
);
const pageP = withTimeout(
contextP.then((c) => c.newPage()),
`Failed to create page in ${browserName} in under %n`
);
const dtpP = pageP.then(domToPlaywright);
const globalStylesP = withTimeout(
resolveStyleInput(stylesInput),
`Failed to global resolve style input for ${browserName} in under %n`
);
const q = (0, import_ichschwoer.createQueue)(1);
return {
name: browserName,
getPlaywright() {
return __async(this, null, function* () {
return {
browser: yield browserP,
context: yield contextP,
page: yield pageP
};
});
},
updatePage(element, { transitions = false, styles: pageStylesP } = {}) {
return q.push(() => __async(this, null, function* () {
const { update } = yield dtpP;
const page = yield pageP;
const styles = yield globalStylesP;
yield withTimeout(
update(element),
`Failed to update page within ${browserName} in under %n`
);
yield withTimeout(
page.addStyleTag(styles),
`Failed to add global styles to page within ${browserName} in under %n`
);
if (pageStylesP) {
const pageStyles = yield withTimeout(
resolveStyleInput(pageStylesP),
`Failed to resolve page style input for ${browserName} in under %n`
);
yield withTimeout(
page.addStyleTag(pageStyles),
`Failed to add page styles to page within ${browserName} in under %n`
);
}
if (!transitions) {
yield withTimeout(
page.addStyleTag({ content: DISABLE_TRANSITIONS }),
`Failed to disable transitions within ${browserName} in under %n`
);
}
}));
},
getStyles(element, styles, options) {
return q.push(() => __async(this, null, function* () {
const { select } = yield dtpP;
const page = yield pageP;
return withTimeout(
getStyles(page, select(element), styles, options),
`Failed to get styles within ${browserName} in under %n`
);
}));
},
hover(element) {
return q.push(() => __async(this, null, function* () {
const { select } = yield dtpP;
const page = yield pageP;
yield withTimeout(
page.hover(select(element)),
`Failed to hover element within ${browserName} in under %n`
);
}));
},
focus(element) {
return q.push(() => __async(this, null, function* () {
const { select } = yield dtpP;
const page = yield pageP;
yield withTimeout(
page.focus(select(element)),
`Failed to focus element within ${browserName} in under %n`
);
}));
}
};
}
function cleanup() {
return __async(this, null, function* () {
const toBeCleared = __spreadValues({}, cache);
for (const key in cache) {
delete cache[key];
}
for (const key in toBeCleared) {
const browser = yield toBeCleared[key];
for (const context of browser.contexts()) {
yield context.close();
}
yield browser.close();
}
});
}
if (typeof afterAll === "function") {
afterAll(cleanup);
}
// src/getRealStyles.ts
function isDocument(elm) {
return Boolean(elm.body);
}
function getElement(elm) {
return isDocument(elm) ? elm.body : elm;
}
function getRealStyles(_0) {
return __async(this, arguments, function* ({
browser = "chromium",
css,
doc,
element = getElement(doc),
hover,
focus,
getStyles: getStyles2,
transitions,
options,
preparePage
}) {
const sb = launchPage(browser, css);
const { page, context } = yield sb.getPlaywright();
yield preparePage == null ? void 0 : preparePage(page);
yield sb.updatePage(doc, { transitions });
if (focus) {
yield sb.focus(focus);
}
if (hover) {
yield sb.hover(hover);
}
const styles = yield sb.getStyles(element, getStyles2, options);
yield page.close();
yield context.close();
return styles;
});
}
// src/toCss.ts
var import_lodash2 = __toESM(require("lodash.kebabcase"), 1);
function toCss(style) {
return Object.keys(style).map((key) => `${(0, import_lodash2.default)(key).toLowerCase()}: ${style[key]};`).join("\n");
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
PLAYWRIGHT_BROWSERS,
cleanup,
getRealStyles,
launch,
normalizeValue,
toCss
});
//# sourceMappingURL=index.cjs.map