Skip to content

Instantly share code, notes, and snippets.

@graffhyrum
Last active May 9, 2023 23:21
Show Gist options
  • Select an option

  • Save graffhyrum/b57f47bcedfe8f1b166d4317e3c115c0 to your computer and use it in GitHub Desktop.

Select an option

Save graffhyrum/b57f47bcedfe8f1b166d4317e3c115c0 to your computer and use it in GitHub Desktop.
import {Locator} from '@playwright/test';
/**
* Wait for `elem` to have no mutations for a period of
* `noMutationDuration` ms. If `timeout` ms elapse without a "no mutation"
* period of sufficient length, throw an error.
* @param elem
* @param noMutationDuration
* @param mutTimeout
* @param waitForFirstMutation If true, wait until the first mutation before
* starting to wait for the `noMutationDuration` period.
*/
export async function waitForMutationToStop(
elem: Locator,
noMutationDuration = 500,
mutTimeout = 10 * 1000,
waitForFirstMutation = false
): Promise<void> {
return elem.evaluate(
async (
elem,
{noMutationDuration, timeout, waitForFirstMutation}
): Promise<void> => {
return new Promise<void>((resolve, reject) => {
const config = {
attributes: true,
childList: true,
characterData: true,
subtree: true,
};
let lastMutationTime = waitForFirstMutation ? 0 : Date.now();
let resolveTimeout: ReturnType<typeof setTimeout>;
const observer = new MutationObserver(callback);
observer.observe(elem, config);
resetTimeout();
const rejectTimeout = setTimeout(() => {
observer.disconnect();
reject(new Error(`Mutation timeout exceeded: ${timeout} ms`));
}, timeout);
function callback() {
lastMutationTime = Date.now();
clearTimeout(resolveTimeout);
resetTimeout();
}
function resetTimeout() {
resolveTimeout = setTimeout(checkTimeout, noMutationDuration);
}
function checkTimeout() {
if (Date.now() - lastMutationTime > noMutationDuration) {
observer.disconnect();
clearTimeout(resolveTimeout);
resolve();
} else {
resetTimeout();
}
}
});
},
{noMutationDuration, timeout: mutTimeout, waitForFirstMutation}
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment