DEV Community

Cover image for Introducing Multi-window Tests (Beta)
TestCafe
TestCafe

Posted on • Originally published at devexpress.github.io

Introducing Multi-window Tests (Beta)

Modern web apps often launch new browser windows to authenticate users through third-party websites or display additional interactive content.

TestCafe v1.9.0 introduces partial support for multi-window tests. You can now use client-side calls to open and close browser windows. The updated API includes additional window management methods. During the 'beta' stage, this functionality is only enabled in local instances of Chrome and Firefox. Keep in mind that this feature is not ready for use in production environments. Both the syntax and capabilities are subject to change.

Client-side window events

The TestCafe browser automation driver detects and automatically activates newly launched windows. After the content is loaded, and all asynchronous requests are resolved, the test continues in the new window. When that window is closed, TestCafe switches back to the parent window and resumes the test.

The sample code below demonstrates an OAuth login scenario. Lines 8 through 10 run in the external OAuth window.

fixture('Login via <Service Name>')
    .page('https://my-page');
test('Should log in via <Service Name>', async t => {
    await t
        .click('#login-popup')
        .typeText('#username', 'username')
        .typeText('#pass', 'mySecret')
        .click('#submit')
        .expect(Selector('#user').textContent).eql('Hello %Username%!'); //Make sure we are logged in
});
Enter fullscreen mode Exit fullscreen mode

A scheme that illustrates automatic window switching

You do not need to write extra code to create basic multi-window tests. When you need to arbitrarily open, close and switch between windows, use the TestCafe API.

Switch between windows

The t.switchToPreviousWindow method activates the last active window. If you only have two windows open, this method will cycle between them. This is useful in a variety of scenarios.

Imagine, for example, that you're testing a real estate listings website. You want to make sure that once a new property is added, it appears in the window with all available listings. The following test implements this scenario:

fixture('Property List')
    .page('https://url.com/properties'); // Open the listings page
test('Check the property list', async t => {
    await t
        .openWindow('https://url.com/addnewproperty') // Open the 'add new property' page in a new window
        .click('#make-public') // Publish the listing
        .switchToPreviousWindow() // Go back to the listings page
        .expect(Selector('.property-list li').textContent).eql('New '); // Check if the new listing is displayed
});  
Enter fullscreen mode Exit fullscreen mode

A scheme that illustrates switching between windows

Manage multiple windows

Test scenarios with more than two open windows require more precision. The t.switchToWindow method can activate any open browser window if you pass a window descriptor object or a predicate function with the window description.

To obtain a window descriptor, call the t.getCurrentWindow method or save the return value when you open a new window.

const windowDesc = await t.openWindow('https://devexpress.github.io/testcafe/');
await t.switchToWindow(windowDesc);
Enter fullscreen mode Exit fullscreen mode

The predicate function must contain a description of the window's URL or title. The URL object has the same structure as its Node.JS counterpart.

await t
    .openWindow('https://devexpress.github.io/testcafe/')
    .switchToWindow(({url}) => url.pathname === '/testcafe');
Enter fullscreen mode Exit fullscreen mode

Imagine you are debugging a task manager app. To ensure that both the task list and the notification feed are updated in real time, use the t.switchToWindow method.

fixture('Tasks View')
    .page('https://url.com/add-task');  

test('Add a new task', async t => {  
    await t
        .openWindow('https://url.com/tasks') // Open a new window with the task list
        .openWindow('https://url.com/feed') // Open the notification feed
        .switchToWindow(({url}) => url.pathname === '/add-task') // Go back to the new task form
        .typeText('#task-description', 'Redesign the landing page by 1 Feb') // Fill in the new task form
        .click('#submit-task') // Submit the task
        .switchToWindow(({url}) => url.pathname === '/tasks') // Switch back to the task list
        .expect(Selector('.task-item').count).eql(1) // Check if the new task is displayed
        .switchToWindow(({url}) => url.pathname === 'feed') // Switch to the notification feed
        .expect(Selector('.message').textContent).eql('Redesign the landing page by 1 Feb'); // Check for the corresponding notification
});  
Enter fullscreen mode Exit fullscreen mode

A scheme that illustrates the task manager example

API overview

The updated API includes a number of useful window management methods.

Try the new API and let us know what you think

To try the functionality described in this article:

  • Install TestCafe version 1.9.0 or later;
  • Create a test scenario that incorporates more than one browser window;
  • Include the window management methods from this article in the test.

The TestCafe team is proud to create API that realistically model user behavior. If you find that the new window management capabilities can be modified to better serve your needs, please let us know. Submit your feedback and bug reports to our GitHub repository.

Refer to the TestCafe help topics for additional information about these methods.

Top comments (0)