WebDriver/Selenium 2 Node.js client for browser automation and testing
—
Powerful waiting mechanisms with built-in asserters for handling dynamic content and asynchronous operations in web applications.
Wait for custom conditions using asserter functions.
/**
* Wait for a condition to be satisfied using an asserter
* @param asserter - Asserter function or object
* @param timeout - Maximum wait time in milliseconds (default: 1000)
* @param pollFreq - Polling frequency in milliseconds (default: 200)
* @param cb - Callback receiving (err, value)
*/
waitFor(asserter: Asserter, timeout?: number, pollFreq?: number, cb?: callback): any;
/**
* Base asserter class for creating custom wait conditions
*/
class Asserter {
constructor(assertFunction: (target: any, callback: function) => void);
}Usage Examples:
const wd = require('wd');
// Wait for element to have non-empty text
browser.elementById('status-message', function(err, element) {
browser.waitFor(wd.asserters.nonEmptyText, 5000, function(err, value) {
console.log('Element now has text:', value);
});
});
// Custom asserter
const customAsserter = new wd.Asserter(function(target, callback) {
target.text(function(err, text) {
if (err) return callback(err);
const satisfied = text.includes('Success');
callback(null, satisfied, text);
});
});
browser.elementById('result', function(err, element) {
browser.waitFor(customAsserter, 10000, function(err, text) {
console.log('Success message appeared:', text);
});
});Wait for elements to exist, be visible, or meet other conditions.
/**
* Wait for element to exist in DOM
* @param using - Selector strategy
* @param value - Selector value
* @param timeout - Maximum wait time in milliseconds
* @param cb - Callback receiving (err, element)
*/
waitForElement(using: string, value: string, timeout?: number, cb?: callback): Element;
/**
* Wait for multiple elements to exist
* @param using - Selector strategy
* @param value - Selector value
* @param timeout - Maximum wait time in milliseconds
* @param cb - Callback receiving (err, elements)
*/
waitForElements(using: string, value: string, timeout?: number, cb?: callback): Element[];
/**
* Wait for element to be visible
* @param using - Selector strategy
* @param value - Selector value
* @param timeout - Maximum wait time in milliseconds
* @param pollFreq - Polling frequency in milliseconds
* @param cb - Callback receiving (err, element)
*/
waitForVisible(using: string, value: string, timeout?: number, pollFreq?: number, cb?: callback): Element;
/**
* Wait for element by ID
* @param id - Element ID
* @param timeout - Maximum wait time in milliseconds
* @param cb - Callback receiving (err, element)
*/
waitForElementById(id: string, timeout?: number, cb?: callback): Element;
/**
* Wait for element by CSS selector
* @param selector - CSS selector
* @param timeout - Maximum wait time in milliseconds
* @param cb - Callback receiving (err, element)
*/
waitForElementByCss(selector: string, timeout?: number, cb?: callback): Element;Usage Examples:
// Wait for dynamically loaded element
browser.waitForElementById('dynamic-content', 10000, function(err, element) {
if (err) {
console.log('Element did not appear within 10 seconds');
return;
}
console.log('Dynamic content loaded');
element.text(function(err, text) {
console.log('Content:', text);
});
});
// Wait for AJAX-loaded elements
browser.waitForElementsByCss('.search-result', 15000, function(err, results) {
console.log('Found', results.length, 'search results');
});
// Wait for element to be visible (not just present in DOM)
browser.waitForVisible('css selector', '.modal-dialog', 5000, function(err, modal) {
console.log('Modal dialog is now visible');
});
// Promise chain waiting
browser
.elementById('search-button')
.click()
.waitForElementsByCss('.search-result', 10000)
.then(results => {
console.log('Search completed with', results.length, 'results');
});Wait for JavaScript expressions to evaluate to true.
/**
* Wait for JavaScript condition to be true
* @param jsCondition - JavaScript expression as string
* @param timeout - Maximum wait time in milliseconds
* @param pollFreq - Polling frequency in milliseconds
* @param cb - Callback receiving (err, value)
*/
waitForJsCondition(jsCondition: string, timeout?: number, pollFreq?: number, cb?: callback): any;
/**
* Alias for waitForJsCondition
*/
waitForCondition(jsCondition: string, timeout?: number, pollFreq?: number, cb?: callback): any;
/**
* Wait for JavaScript condition evaluated in browser context
* @param jsCondition - JavaScript expression as string
* @param timeout - Maximum wait time in milliseconds
* @param pollFreq - Polling frequency in milliseconds
* @param cb - Callback receiving (err, value)
*/
waitForConditionInBrowser(jsCondition: string, timeout?: number, pollFreq?: number, cb?: callback): any;Usage Examples:
// Wait for AJAX request to complete
browser.waitForJsCondition('window.ajaxInProgress === false', 10000, function(err) {
console.log('AJAX requests completed');
});
// Wait for JavaScript library to load
browser.waitForCondition('typeof jQuery !== "undefined"', 5000, function(err) {
console.log('jQuery library loaded');
});
// Wait for custom application state
browser.waitForConditionInBrowser('window.app && window.app.isReady', 15000, function(err) {
console.log('Application is ready');
});
// Wait for element count condition
browser.waitForJsCondition(
'document.querySelectorAll(".item").length >= 5',
8000,
function(err) {
console.log('At least 5 items are now present');
}
);
// Promise chain JS condition waiting
browser
.elementById('load-more')
.click()
.waitForCondition('document.querySelector(".loading") === null', 10000)
.then(() => {
console.log('Loading spinner disappeared');
});Pre-built asserter functions for common waiting scenarios.
const asserters: {
/**
* Assert element has non-empty text content
*/
nonEmptyText: Asserter;
/**
* Assert element text includes specific content
* @param content - Text content to look for
*/
textInclude(content: string): Asserter;
/**
* Assert element is displayed (visible)
*/
isDisplayed: Asserter;
/**
* Assert element is not displayed (hidden)
*/
isNotDisplayed: Asserter;
/**
* Assert JavaScript condition evaluates to true
* @param jsExpr - JavaScript expression
* @param safe - Use safe execution (default: true)
*/
jsCondition(jsExpr: string, safe?: boolean): Asserter;
// Deprecated asserters (use alternatives above)
isVisible: Asserter; // Use isDisplayed
isHidden: Asserter; // Use isNotDisplayed
};Usage Examples:
const wd = require('wd');
// Wait for element to have text
browser.elementById('message', function(err, element) {
browser.waitFor(wd.asserters.nonEmptyText, 5000, function(err, text) {
console.log('Message appeared:', text);
});
});
// Wait for specific text content
browser.elementById('status', function(err, element) {
const successAsserter = wd.asserters.textInclude('Success');
browser.waitFor(successAsserter, 10000, function(err, text) {
console.log('Success status confirmed:', text);
});
});
// Wait for element to become visible
browser.elementByCss('.hidden-initially', function(err, element) {
browser.waitFor(wd.asserters.isDisplayed, 3000, function(err) {
console.log('Element is now visible');
});
});
// Wait for element to be hidden
browser.elementById('loading-spinner', function(err, element) {
browser.waitFor(wd.asserters.isNotDisplayed, 15000, function(err) {
console.log('Loading spinner is now hidden');
});
});
// Wait for JavaScript condition
const jsAsserter = wd.asserters.jsCondition('window.dataLoaded === true');
browser.waitFor(jsAsserter, 8000, function(err) {
console.log('Data loading completed');
});Complex waiting scenarios combining multiple conditions.
Usage Examples:
// Wait for multiple conditions in sequence
browser
.elementById('submit-form')
.click()
.waitFor(wd.asserters.jsCondition('document.querySelector(".loading")'), 1000) // Loading appears
.waitFor(wd.asserters.jsCondition('!document.querySelector(".loading")'), 10000) // Loading disappears
.waitForElementById('success-message', 5000)
.text()
.then(message => console.log('Form submitted:', message));
// Custom asserter for complex conditions
const complexAsserter = new wd.Asserter(function(browser, callback) {
browser.elementsByCss('.item', function(err, items) {
if (err) return callback(err);
if (items.length < 3) {
return callback(null, false); // Not satisfied yet
}
// Check if all items are visible
let visibleCount = 0;
let completed = 0;
items.forEach((item, index) => {
item.isDisplayed(function(err, visible) {
if (visible) visibleCount++;
completed++;
if (completed === items.length) {
const satisfied = visibleCount >= 3;
callback(null, satisfied, visibleCount);
}
});
});
});
});
browser.waitFor(complexAsserter, 10000, function(err, visibleCount) {
console.log('At least 3 items are visible:', visibleCount);
});
// Timeout handling
browser.waitForElementById('slow-element', 5000, function(err, element) {
if (err && err.message.includes('timeout')) {
console.log('Element did not appear within timeout, continuing with fallback');
// Implement fallback behavior
} else if (err) {
throw err;
} else {
console.log('Element found:', element);
}
});Basic sleep functionality for fixed delays.
/**
* Sleep for specified duration
* @param ms - Duration in milliseconds
* @param cb - Callback receiving (err)
*/
sleep(ms: number, cb?: callback): void;Usage Examples:
// Simple delay
browser.sleep(2000, function() {
console.log('Waited 2 seconds');
});
// Promise chain with sleep
browser
.elementById('animate-button')
.click()
.sleep(1000) // Wait for animation
.elementByCss('.animated-element')
.isDisplayed()
.then(visible => console.log('Animation completed:', visible));Install with Tessl CLI
npx tessl i tessl/npm-wd