Skip to main content

Writing tests

Introduction​

copilotbrowser tests are simple: they perform actions and assert the state against expectations.

copilotbrowser automatically waits for actionability checks to pass before performing each action. You don't need to add manual waits or deal with race conditions. copilotbrowser assertions are designed to describe expectations that will eventually be met, eliminating flaky timeouts and racy checks.

You will learn

First test​

Take a look at the following example to see how to write a test.

tests/example.spec.ts
import { test, expect } from '@copilotbrowser/copilotbrowser/test';

test('has title', async ({ page }) => {
await page.goto('https://dayour.github.io/copilotbrowser/');

// Expect a title "to contain" a substring.
await expect(page).toHaveTitle(/copilotbrowser/);
});

test('get started link', async ({ page }) => {
await page.goto('https://dayour.github.io/copilotbrowser/');

// Click the get started link.
await page.getByRole('link', { name: 'Get started' }).click();

// Expects page to have a heading with the name of Installation.
await expect(page.getByRole('heading', { name: 'Installation' })).toBeVisible();
});
note

Add // @ts-check at the start of each test file when using JavaScript in VS Code to get automatic type checking.

Actions​

Most tests start by navigating to a URL. After that, the test interacts with page elements.

await page.goto('https://dayour.github.io/copilotbrowser/');
page.goto("https://dayour.github.io/copilotbrowser/")

copilotbrowser waits for the page to reach the load state before continuing. Learn more about Page.goto() options.

Interactions​

Performing actions starts with locating elements. copilotbrowser uses Locators API for that. Locators represent a way to find element(s) on the page at any moment. Learn more about the different types of locators available.

copilotbrowser waits for the element to be actionable before performing the action, so you don't need to wait for it to become available.

// Create a locator.
const getStarted = page.getByRole('link', { name: 'Get started' });

// Click it.
await getStarted.click();

In most cases, it'll be written in one line:

await page.getByRole('link', { name: 'Get started' }).click();

Basic actions​

Here are the most popular copilotbrowser actions. For the complete list, check the Locator API section.

ActionDescription
Locator.check()Check the input checkbox
Locator.click()Click the element
Locator.uncheck()Uncheck the input checkbox
Locator.hover()Hover mouse over the element
Locator.fill()Fill the form field, input text
Locator.focus()Focus the element
Locator.press()Press single key
Locator.setInputFiles()Pick files to upload
Locator.selectOption()Select option in the drop down

Assertions​

copilotbrowser includes test assertions in the form of expect function. To make an assertion, call expect(value) and choose a matcher that reflects the expectation.

copilotbrowser includes async matchers that wait until the expected condition is met. Using these matchers makes tests non-flaky and resilient. For example, this code waits until the page gets the title containing "copilotbrowser":

await expect(page).toHaveTitle(/copilotbrowser/);

Here are the most popular async assertions. For the complete list, see assertions guide:

AssertionDescription
LocatorAssertions.toBeChecked()Checkbox is checked
LocatorAssertions.toBeEnabled()Control is enabled
LocatorAssertions.toBeVisible()Element is visible
LocatorAssertions.toContainText()Element contains text
LocatorAssertions.toHaveAttribute()Element has attribute
LocatorAssertions.toHaveCount()List of elements has given length
LocatorAssertions.toHaveText()Element matches text
LocatorAssertions.toHaveValue()Input element has value
PageAssertions.toHaveTitle()Page has title
PageAssertions.toHaveURL()Page has URL

copilotbrowser also includes generic matchers like toEqual, toContain, toBeTruthy that can be used to assert any conditions. These assertions do not use the await keyword as they perform immediate synchronous checks on already available values.

expect(success).toBeTruthy();

Test Isolation​

copilotbrowser Test is based on the concept of test fixtures such as the built in page fixture, which is passed into your test. Pages are isolated between tests due to the Browser Context, which is equivalent to a brand new browser profile. Every test gets a fresh environment, even when multiple tests run in a single browser.

tests/example.spec.ts
import { test } from '@copilotbrowser/copilotbrowser/test';

test('example test', async ({ page }) => {
// "page" belongs to an isolated BrowserContext, created for this specific test.
});

test('another test', async ({ page }) => {
// "page" in this second test is completely isolated from the first test.
});

Using Test Hooks​

You can use various test hooks such as test.describe to declare a group of tests and test.beforeEach and test.afterEach which are executed before/after each test. Other hooks include the test.beforeAll and test.afterAll which are executed once per worker before/after all tests.

tests/example.spec.ts
import { test, expect } from '@copilotbrowser/copilotbrowser/test';

test.describe('navigation', () => {
test.beforeEach(async ({ page }) => {
// Go to the starting url before each test.
await page.goto('https://dayour.github.io/copilotbrowser/');
});

test('main navigation', async ({ page }) => {
// Assertions use the expect API.
await expect(page).toHaveURL('https://dayour.github.io/copilotbrowser/');
});
});

What's Next​