docsify/test/helpers/wait-for.js
Joe Pea 62d756c447 refactor: convert to ES Modules and remove traces of CommonJS except in Rollup config because some dependencies are still CommonJS
BREAKING: The new project layout might break in some tooling setups.

We've added an exports field to `package.json` to specify where
statements like `import ... from 'docsify'` will import from, and left
the `main` and `unpkg` fields as-is for backwards compatibility with the
global <script> import method. Most people who use a non-module
`<script>` tag to import Docsify will not notice a difference. Anyone
else who is importing Docsify into a specilized build setup using
`import` statements has a chance of being broken, so we've marked this
as BREAKING.
2023-06-29 19:02:08 -07:00

129 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);
});
});
}
export { waitForFunction, waitForSelector, waitForText };