My First Playwright Tests
Tags: playwright, testing, vscode
Published: 2023-11-17 14:18:54

**A blog series about playing and writing in 🎭**
<br>
I'm a developer learning about web accessibility, and I would like to add Playwright to my toolset for testing web accessibility compliance.

So far, I've found that it offers straightforward syntax and excellent automation capabilities. Plus, the best documentation in the universe. (Yes, I believe aliens would use Playwright for some of their testing needs!)

This post is about the first three tests I wrote and how I applied them to my portfolio site. 

---

## Getting Started with 🎭
First, to get started (i.e., installation, how to run tests, etc.), I highly recommend Debbie O’Brien’s series of articles published on dev.to. I've included the link below in the Resources section.

Once installed, Playwright comes with example tests to help you get started. I adapted some of these examples to create three tests specifically for my portfolio site:

✔️ To navigate to the home page of my portfolio site and check if the title matches an expected string. 
✔️ To check for the visibility of the home page’s heading.
✔️ To check whether the “My Projects” link is functional.

**Note**: My site is still in construction, so expect to find errors beyond those tested here.

Here are all three of the tests:

```js
import { test, expect } from '@playwright/test';

test('has title', async ({ page }) => {
    await page.goto('https://corinamurg.netlify.app/');

    await expect(page).toHaveTitle(/Corina's Portfolio/);
});


test('has heading', async ({ page }) => {
    await page.goto('https://mywebsite.com/');

    await expect(page.getByRole('heading', {name: 'HELLO, I’m CORINA!'})).toBeVisible();
});


test('My Projects link', async ({ page }) => {
    await page.goto('https://corinamurg.netlify.app/');

    await page.getByRole('link', {name: 'My Projects'}).click();
});

```
<br>
## Understanding the Code for Test 1
Let's break the code down into smaller steps and analyze them!

**Step 1:** We have to import two functions from Playwright: `test` and `expect`:

```js
import { test, expect } from '@playwright/test';
```

- the `test` function is used to define an individual test. 
- `expect` is an assertion function that checks whether a certain condition is met. 

**Heads up**: the term **assertion** frequently appears in Playwright. An assertion is a check within a test that verifies whether certain conditions are met. So it basically evaluates a specific condition and passes or fails the test based on the result.


**Step 2:** Define a test named `has title`

```js
test('has title', async ({ page }) => {
```

**Step 3:** Navigate to my website
   

```js
 await page.goto('https://corinamurg.netlify.app/');
```

**Step 4:**  Add an assertion to check if the webpage's title contains the text "Corina's Portfolio"    

```js
await expect(page).toHaveTitle(/Corina's Portfolio/);
```
<br>

**A few important notes**
- the `test` function requires a string as its first argument to name the test, and a function as its second argument. This function is where you write the actual test code. It’s an asynchronous function that receives a `page` object. 
- a test interacts with web pages through this `page` object, which is an instance of the `Page` class. The `Page` class provides a wide range of methods that allows us to simulate any possible user interactions and scenario. For example, use  `.goto()`  to navigate to URLs, `page.click()` or `page.fill()` to interact with elements,  `page.locator()` to query the DOM. I highly recommend checking out [the documentation on the Page class and its methods](https://playwright.dev/docs/pom). 
- `await` is necessary because Playwright operates asynchronously. It performs actions in a browser environment that requires waiting for the actions to complete before moving to the next step.

Now let’s look briefly at the other two tests as well.
<br>
## Test 2
```js
// Define a test named 'has heading' 
test('has heading', async ({ page }) => {
    await page.goto('https://corinamurg.netlify.app/')
    // Expect page to have a heading with name of 'HELLO, I’m CORINA!'
    await expect(page.getByRole('heading', { name: 'HELLO, I’m CORINA!' })).toBeVisible();
});

```
<br>

## Test 3

```js
// Define a test named 'My Projects link'
test('My Projects link', async ({ page }) => {
    await page.goto('https://corinamurg.netlify.app/')
  
    // simulate a user clicking on the 'My Projects' link
    await page.getByRole('link', { name: 'My Projects' }).click();
});

```
<br>

## Playing with Errors
As an experiment, I modified the `has title` test with a different expected title, which, as anticipated, led to a failed test due to the mismatch.

Here is the (quite long) error log:

```js
Error: Timed out 5000ms waiting for expect(locator).toHaveTitle(expected) 
Locator: locator(':root') 
Expected pattern: /My site/ 
Received string: "Corina's Portfolio" 
Call log: - expect.toHaveTitle with timeout 5000ms 
- waiting for locator(':root') 
- locator resolved to <html lang="en">…</html> 
- unexpected value "Corina's Portfolio" 
- locator resolved to <html lang="en">…</html> 
- unexpected value "Corina's Portfolio" 
- locator resolved to <html lang="en">…</html> 
- unexpected value "Corina's Portfolio" 
- locator resolved to <html lang="en">…</html> 
- unexpected value "Corina's Portfolio" 
- locator resolved to <html lang="en">…</html> 
- unexpected value "Corina's Portfolio" 
- locator resolved to <html lang="en">…</html> 
- unexpected value "Corina's Portfolio
- locator resolved to <html lang="en">…</html> 
- unexpected value "Corina's Portfolio" 
- locator resolved to <html lang="en">…</html> 
- unexpected value "Corina's Portfolio"
```

The `expect` function was waiting for the page title to match "My site", but instead found "Corina's Portfolio". This mismatch between expected and actual results caused the test to fail.

The repeated lines like `-unexpected value 'Corina's Portfolio'` and `-locator resolved to <html lang='en'>…</html>` show that **Playwright** was continually checking the page title within the specified timeout period (5000ms). Each line likely represents an attempt to recheck the title against the expected value. Of course, it consistently found a value that did not match the expected pattern. 
<br>

## Conclusion 😊
I'm thrilled that my first three tests were successful! To create these tests I adapted the example tests that Playwright adds at installation. In the next post I will talk about another test that I created with just a click of a button! Seriously!
<br>

## Resources

[Debbie O’Brien’s Playwright Series on dev.to](https://dev.to/debs_obrien/series/25202)

[Playwright Documentation](https://playwright.dev/docs/intro)
<br>

**Image credit**: Photo by [Alex Kondratiev](https://unsplash.com/@alexkondratiev)

Description: The image shows a hand pouring a blue liquid from a glass test tube into a flask with red liquid, and another hand pouring a green liquid into the flask. The background is plain white.