Previous: Advanced WebDriverIO Features Next: Page Object Model

Module 5: API Testing with WebDriverIO

Overview

WebDriverIO provides a rich and extensive API that allows testers to interact with web applications in sophisticated ways. This module takes a deep dive into the WebDriverIO API, exploring advanced commands, browser interactions, and utility functions that can enhance your test automation capabilities.

Learning Objectives

By the end of this module, you will be able to:

  1. Understand and utilize advanced WebDriverIO commands
  2. Implement complex browser interactions and manipulations
  3. Work with browser windows, frames, and alerts
  4. Leverage WebDriverIO utility functions for common testing scenarios
  5. Debug and troubleshoot WebDriverIO commands

5.1 Advanced Element Commands

Beyond Basic Interactions

WebDriverIO provides numerous commands beyond the basic click, setValue, and getText operations:

// Check if element exists
const exists = await $('#element').isExisting();

// Check if element is displayed
const isVisible = await $('#element').isDisplayed();

// Check if element is enabled
const isEnabled = await $('#element').isEnabled();

// Check if element is selected (for checkboxes, radio buttons, options)
const isSelected = await $('#checkbox').isSelected();

// Get element location
const location = await $('#element').getLocation();
console.log(`X: ${location.x}, Y: ${location.y}`);

// Get element size
const size = await $('#element').getSize();
console.log(`Width: ${size.width}, Height: ${size.height}`);

// Get computed CSS property
const color = await $('#element').getCSSProperty('color');
console.log(`Color: ${color.value}`);

Working with Multiple Elements

// Find all elements matching a selector
const elements = await $$('.item');

// Get count of elements
const count = await $$('.item').length;

// Filter elements
const visibleElements = await $$('.item').filter(async (element) => {
    return await element.isDisplayed();
});

// Find a specific element in a collection
const thirdElement = await $$('.item')[2];

// Check if any element in a collection contains specific text
const hasText = await $$('.item').some(async (element) => {
    const text = await element.getText();
    return text.includes('specific text');
});

Shadow DOM Access

WebDriverIO provides excellent support for working with Shadow DOM:

// Access element in shadow DOM
const shadowElement = await $('#shadow-host').shadow$('.shadow-element');

// Access multiple elements in shadow DOM
const shadowElements = await $('#shadow-host').shadow$$('.shadow-element');

// Nested shadow DOM
const nestedElement = await $('#outer-host').shadow$('#inner-host').shadow$('.inner-element');

5.2 Advanced Browser Commands

Browser Navigation

// Navigate to URL
await browser.url('https://example.com');

// Get current URL
const url = await browser.getUrl();

// Navigate back
await browser.back();

// Navigate forward
await browser.forward();

// Refresh page
await browser.refresh();

// Get page title
const title = await browser.getTitle();

Browser Windows and Tabs

// Get current window handle
const currentWindow = await browser.getWindowHandle();

// Get all window handles
const handles = await browser.getWindowHandles();

// Switch to specific window
await browser.switchToWindow(handles[1]);

// Create new window
await browser.newWindow('https://example.com');

// Close current window
await browser.closeWindow();

5.3 Advanced Waiting Strategies

Custom Wait Conditions

// Wait until element is clickable
await $('#button').waitForClickable({ timeout: 5000 });

// Wait until element exists
await $('#element').waitForExist({ timeout: 5000 });

// Wait until element is displayed
await $('#element').waitForDisplayed({ timeout: 5000 });

// Wait for custom condition
await browser.waitUntil(async () => {
    const text = await $('#element').getText();
    return text === 'Expected Text';
}, {
    timeout: 10000,
    timeoutMsg: 'Expected text to be different after 10s',
    interval: 500  // Check every 500ms
});

5.4 JavaScript Execution

Executing JavaScript

// Execute simple script
const title = await browser.execute(() => {
    return document.title;
});

// Execute with arguments
const sum = await browser.execute((a, b) => {
    return a + b;
}, 5, 10);

// Modify DOM
await browser.execute(() => {
    document.body.style.backgroundColor = 'red';
});

5.5 File Uploads and Downloads

Handling File Uploads

// Upload file using input element
const filePath = '/path/to/file.jpg';
const remoteFilePath = await browser.uploadFile(filePath);
await $('#file-input').setValue(remoteFilePath);

// Upload multiple files
const filePaths = ['/path/to/file1.jpg', '/path/to/file2.jpg'];
const remoteFilePaths = await Promise.all(filePaths.map(path => browser.uploadFile(path)));
await $('#multiple-file-input').setValue(remoteFilePaths.join('\n'));

5.6 Performance Testing

Measuring Page Load Performance

// Get performance metrics
const performanceTiming = await browser.execute(() => {
    return JSON.stringify(performance.timing);
});

const metrics = JSON.parse(performanceTiming);

// Calculate key metrics
const pageLoadTime = metrics.loadEventEnd - metrics.navigationStart;
const domContentLoaded = metrics.domContentLoadedEventEnd - metrics.navigationStart;

console.log(`Page Load Time: ${pageLoadTime}ms`);
console.log(`DOM Content Loaded: ${domContentLoaded}ms`);

Summary

This module provided a comprehensive deep dive into the WebDriverIO API, covering advanced element and browser commands, waiting strategies, JavaScript execution, file handling, and performance testing. By mastering these advanced features, you can create more robust, efficient, and powerful test automation solutions.

Key takeaways:

  1. WebDriverIO provides a rich set of commands for complex element interactions and browser manipulations
  2. Advanced waiting strategies help handle asynchronous behavior and dynamic content
  3. JavaScript execution enables powerful browser-side operations and data extraction
  4. Performance testing capabilities help ensure optimal application performance
  5. Debugging tools and techniques are essential for troubleshooting test failures

In the next module, we'll explore the Page Object Model pattern to organize and structure your test code effectively.

Previous: Advanced WebDriverIO Features Next: Page Object Model