kayle
Version:
Extremely fast and accurate accessibility engine built for any headless tool like playwright or puppeteer.
268 lines • 10.2 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.runActionsList = exports.runAction = exports.actions = void 0;
const failedActionElement = "Failed action: no element matching selector";
exports.actions = [
{
name: "navigate-url",
match: /^navigate to( url)? (.+)$/i,
run: async (_, page, __, matches) => {
const navigateTo = matches[2];
try {
await page.goto(navigateTo);
}
catch (error) {
console.error(`Failed action: Could not navigate to "${navigateTo}"`);
}
},
},
{
name: "click-element",
match: /^click( element)? (.+)$/i,
run: async (_, page, __, matches) => {
const selector = matches[2];
try {
await page.click(selector);
}
catch (error) {
console.error(`${failedActionElement} "${selector}"`);
}
},
},
{
name: "set-field-value",
match: /^set( field)? (.+?) to (.+)$/i,
run: async (_, page, __, matches) => {
const selector = matches[2];
const value = matches[3];
try {
await page.evaluate((targetSelector, desiredValue) => {
const target = document.querySelector(targetSelector);
if (!target) {
return Promise.reject(new Error("No element found"));
}
const prototype = Object.getPrototypeOf(target);
const { set: prototypeValueSetter } = Object.getOwnPropertyDescriptor(prototype, "value") || {};
if (prototypeValueSetter) {
prototypeValueSetter.call(target, desiredValue);
}
else {
target.value = desiredValue;
}
target.dispatchEvent(new Event("input", {
bubbles: true,
}));
return Promise.resolve();
}, selector, value);
}
catch (error) {
console.error(`${failedActionElement} "${selector}"`);
}
},
},
{
name: "clear-field-value",
match: /^clear( field)? (.+?)$/i,
run: async (_, page, __, matches) => {
const selector = matches[2];
try {
await page.evaluate((targetSelector) => {
const target = document.querySelector(targetSelector);
if (!target) {
return Promise.reject(new Error("No element found"));
}
const prototype = Object.getPrototypeOf(target);
const { set: prototypeValueSetter } = Object.getOwnPropertyDescriptor(prototype, "value") || {};
if (prototypeValueSetter) {
prototypeValueSetter.call(target, "");
}
else {
target.value = "";
}
target.dispatchEvent(new Event("input", {
bubbles: true,
}));
return Promise.resolve();
}, selector);
}
catch (error) {
console.error(`${failedActionElement} "${selector}"`);
}
},
},
{
name: "check-field",
match: /^(check|uncheck)( field)? (.+)$/i,
run: async (_, page, __, matches) => {
const checked = matches[1] !== "uncheck";
const selector = matches[3];
try {
await page.evaluate((targetSelector, isChecked) => {
const target = document.querySelector(targetSelector);
if (!target) {
return Promise.reject(new Error("No element found"));
}
target.checked = isChecked;
target.dispatchEvent(new Event("change", {
bubbles: true,
}));
return Promise.resolve();
}, selector, checked);
}
catch (error) {
console.error(`${failedActionElement} "${selector}"`);
}
},
},
{
name: "style",
match: /^style ( content)? (.+?)$/i,
run: async (_, page, __, matches) => {
await page.addStyleTag({
content: matches[2],
});
},
},
{
name: "screen-capture",
match: /^(screen[ -]?capture|capture[ -]?screen)( to)? (.+)$/i,
run: async (_, page, __, matches) => {
await page.screenshot({
path: matches[3],
fullPage: true,
});
},
},
{
name: "pdf",
match: /^pdf( to)? (.+)$/i,
run: async (_, page, __, matches) => {
await page.pdf({
path: matches[3],
});
},
},
{
name: "drag-and-drop",
match: /^drag-and-drop ( element)? (.+)( to ) (target)$/i,
run: async (_, page, __, matches) => {
if (typeof page.dragAndDrop === "function") {
await page.dragAndDrop(matches[1], matches[3]);
}
else if (typeof page?.mouse?.dragAndDrop) {
const positions = await page.$$eval([matches[1], matches[3]], (elements) => elements.map((e) => e.getBoundingClientRect));
await page.dragAndDrop(positions[0], positions[1]);
}
},
},
{
name: "wait-for-url",
match: /^wait for (fragment|hash|host|path|url)( to (not )?be)? ([^\s]+)$/i,
run: async (_, page, __, matches) => {
const expectedValue = matches[4];
const negated = matches[3] !== undefined;
const subject = matches[1];
let property = "";
switch (subject) {
case "fragment":
case "hash":
property = "hash";
break;
case "host":
property = "host";
break;
case "path":
property = "pathname";
break;
default:
property = "href";
break;
}
function locationHasProperty(locationProperty, value, isNegated) {
return isNegated
? window.location[locationProperty] !== value
: window.location[locationProperty] === value;
}
await page.waitForFunction(locationHasProperty, {}, property, expectedValue, negated);
},
},
{
name: "wait-for-element-state",
match: /^wait for( element)? (.+)( to be) (added|removed|visible|hidden)$/i,
run: async (_, page, __, matches) => {
const selector = matches[2];
const state = matches[4];
await page.waitForFunction((targetSelector, desiredState) => {
const targetElement = document.querySelector(targetSelector);
if ((targetElement && desiredState === "added") ||
(!targetElement && desiredState === "removed")) {
return true;
}
const visible = !!(targetElement &&
(targetElement.offsetWidth ||
targetElement.offsetHeight ||
targetElement.getClientRects().length));
return ((desiredState === "visible" && visible) ||
(desiredState === "hidden" && !visible));
}, {
polling: 200,
}, selector, state);
},
},
{
name: "wait-for-element-event",
match: /^wait for( element)? (.+) to emit (.+)$/i,
run: async (_, page, __, matches) => {
const selector = matches[2];
const eventType = matches[3];
try {
await page.evaluate((targetSelector, desiredEvent) => {
const target = document.querySelector(targetSelector);
if (!target) {
return Promise.reject(new Error("No element found"));
}
target.addEventListener(desiredEvent, () => {
window._a11yWaitForElementEventFired = true;
}, {
once: true,
});
}, selector, eventType);
await page.waitForFunction(() => {
if (window._a11yWaitForElementEventFired) {
delete window._a11yWaitForElementEventFired;
return true;
}
return false;
}, {
polling: 200,
});
}
catch (error) {
return console.error(`${failedActionElement} "${selector}"`);
}
},
},
{
name: "wait",
match: /^wait (\d+)ms$/i,
run: async (_, __, ___, matches) => {
const waitTime = parseInt(matches[1], 10);
await new Promise((resolve) => setTimeout(resolve, waitTime));
},
},
];
async function runAction(browser, page, options, act, customActions) {
const action = (customActions ?? exports.actions).find((item) => item.match.test(act));
if (!action) {
return console.error(`Failed action: "${act}" cannot be resolved`);
}
await action.run(browser, page, options, act.match(action.match));
}
exports.runAction = runAction;
const runActionsList = async (config) => {
for (const action of config.actions) {
await runAction(config.browser, config.page, config, action);
}
};
exports.runActionsList = runActionsList;
//# sourceMappingURL=action.js.map