docsify/test/helpers/wait-for.js
John Hildenbiddle c49c39a4a2
refactor: Update test environments and lint configuration (#1736)
* Update test environments and lint configuration

Update Jest (unit + integration) and Playwright (e2e) test environments. Includes stability improvements for e2e tests using newer, more stable methods per the Playwright docs.

- Update Jest 26 => 27
- Update Jest-related libs (babel parser)
- Update Playwright 1.8 => Playwright Test 1.18
- Update GitHub CI (action versions, job parallelization, and matrices)
- Update ESLint 5 => 8
- Update ESLint-related libs (parser, prettier, Jest, Playwright)
- Fix test failures on M1-based Macs
- Fix e2e stability issues by replacing PW $ method calls
- Fix ESLint errors
- Fix incorrect CI flag on Jest runs (-ci => --ci)
- Refactor e2e test runner from Jest to Playwright Test
- Refactor e2e test files for Playwright Test
- Refactor fix-lint script name to lint:fix for consistency
- Refactor npm scripts order for readability
- Remove unnecessary configs and libs
- Remove example image snapshots
2022-01-30 21:40:21 -06:00

133 lines
3.1 KiB
JavaScript

const defaults = {
delay: 100,
timeout: 4000,
};
/**
* Waits for specified function to resolve to a truthy value.
*
* @param {Function} fn function to be evaluated until truthy
* @param {*} arg optional argument to pass to `fn`
* @param {Object} options optional parameters
* @returns {Promise} promise which resolves to function result
*/
function waitForFunction(fn, arg, options = {}) {
const settings = {
...defaults,
...options,
};
return new Promise((resolve, reject) => {
let timeElapsed = 0;
const int = setInterval(() => {
let result;
try {
result = fn(arg);
} catch (e) {
// Continue...
}
if (result) {
clearInterval(int);
resolve(result);
}
timeElapsed += settings.delay;
if (timeElapsed >= settings.timeout) {
const msg = `waitForFunction did not return a truthy value (${
settings.timeout
} ms): ${fn.toString()}\n`;
reject(msg);
}
}, settings.delay);
});
}
/**
* Waits for specified CSS selector to be located in the DOM
*
* @param {String} cssSelector CSS selector to query for
* @param {Object} options optional parameters
* @returns {Promise} promise which resolves to first matching element
*/
function waitForSelector(cssSelector, options = {}) {
const settings = {
...defaults,
...options,
};
return new Promise((resolve, reject) => {
let timeElapsed = 0;
const int = setInterval(() => {
const elm = document.querySelector(cssSelector);
if (elm) {
clearInterval(int);
resolve(elm);
}
timeElapsed += settings.delay;
if (timeElapsed >= settings.timeout) {
const msg = `waitForSelector did not match CSS selector '${cssSelector}' (${settings.timeout} ms)`;
reject(msg);
}
}, settings.delay);
});
}
/**
* Waits for specified CSS selector to contain text content
*
* @param {String} cssSelector CSS selector to query for
* @param {String} text text to match
* @param {Object} options optional parameters
* @returns {Promise} promise which resolves to first matching element that contains specified text
*/
function waitForText(cssSelector, text, options = {}) {
const settings = {
...defaults,
...options,
};
return new Promise((resolve, reject) => {
let timeElapsed = 0;
waitForSelector(cssSelector, settings)
.then(elm => {
const int = setInterval(() => {
const isMatch = elm.textContent.includes(text);
if (isMatch) {
clearInterval(int);
resolve(true);
}
timeElapsed += settings.delay;
if (timeElapsed >= settings.timeout) {
const msg = `waitForText did not find '${text}' in CSS selector '${cssSelector}' (${settings.timeout} ms): '${elm.textContent}'`;
reject(msg);
}
}, settings.delay);
})
.catch(() => {
const msg = `waitForText did not match CSS selector '${cssSelector}' (${settings.timeout} ms)`;
reject(msg);
});
});
}
module.exports = {
waitForFunction,
waitForSelector,
waitForText,
};