@funnelenvy-npm/fe-dev-utils
Version:
Helper function to build client side A/B tests
80 lines (79 loc) • 3.4 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const get_element_1 = __importDefault(require("../get-element"));
const on_error_1 = __importDefault(require("../on-error"));
/**
* Poller function that waits for a set of conditions to be true before executing a callback function.
*
* @param options - Options object to configure the function.
* @throws {TypeError} - If `conditions` is not an array, `callback` is not a function,
* or `timeout` and `pollFreq` are not numbers greater than or equal to 1000 and 10, respectively.
*/
const waitForConditions = ({ conditions, callback, activity = null, errorHandler = null, timeout = 10000, pollFreq = 100, }) => {
if (!Array.isArray(conditions)) {
throw new TypeError('The first parameter must be an array');
}
if (typeof callback !== 'function') {
throw new TypeError('The second parameter must be a function');
}
if (typeof timeout !== 'number' || timeout < 1000) {
throw new TypeError('The third parameter must be a number greater than or equal to 1000');
}
const promises = conditions.map((condition) => {
if (typeof condition === 'function') {
return new Promise((resolve, reject) => {
let intervalId;
let timeoutId;
const clearIds = () => {
clearInterval(intervalId);
clearTimeout(timeoutId);
};
intervalId = setInterval(() => {
try {
if (condition()) {
clearIds();
resolve(true);
}
}
catch (err) {
clearIds();
reject(new Error(`Error executing condition function: ${err}`));
}
}, pollFreq);
timeoutId = setTimeout(() => {
clearIds();
reject(new Error(`Condition function timed out: ${condition.toString()}`));
}, timeout);
});
}
return (0, get_element_1.default)({ condition, activity: activity ?? undefined, errorHandler: () => null });
});
Promise.all(promises)
.then((results) => {
// Build an object of elements from string conditions.
// Note: Function conditions resolve to a boolean and aren’t included.
const elements = conditions.reduce((acc, cond, index) => {
if (typeof cond === 'string') {
const result = results[index];
if (result && typeof result.selector === 'string') {
acc[result.selector] = result.elements;
}
}
return acc;
}, {});
// Now that all promises have resolved, fire the callback.
callback(elements);
})
.catch((error) => {
if (errorHandler && typeof errorHandler === 'function') {
errorHandler({ activity, error });
}
else {
(0, on_error_1.default)({ activity: activity ?? undefined, error });
}
});
};
exports.default = waitForConditions;