Getting Started with Playwright in VS Code
Tags: playwright, e2e, testing, vscode
Published: 2023-11-01 17:00:00

Let's take a look at how to install Playwright using the VS Code extension as well as walk through the example so you can fully understand what is happening during each line of the test.

Once you have the [Playwright VS Code extension](https://marketplace.visualstudio.com/items?itemName=ms-playwright.playwright) installed you can type 'install playwright' into the command panel and you will see the default options of which browsers to install. 

![install playwright](https://user-images.githubusercontent.com/13063165/212735039-4fd84b61-c1ca-4296-90de-e5fb307304d8.png)

You can always change this later in the config file. Another cool feature is the install GitHub actions workflow. This will generate a yaml file in a GitHub folder and once you commit your changes to GitHub your tests will run on each pull request with no extra setup needed.

![extension browsers to install and github actions](https://user-images.githubusercontent.com/13063165/212735257-de837172-676f-4c31-8527-7b4b9b34266f.png)

Let's leave the default setup and press *install*. Playwright will install the browser binaries so that you can run your tests against each of the browsers selected on install, chromium, firefox and webkit. Note that you do not need to have these browsers installed for playwright to install the browser binaries and run the tests against these browsers.

Once everything has been installed you can see you now have:
- A GitHub folder with the yaml file for the actions needed to run your tests on each pull request. 
- A test folder with a small example test. 
- An example folder with tests for a ToDo application. 
- The playwright config file which we can use to add a base URL, set up a local web server and add more projects to run our tests against emulated devices as well other configurations.

Let's look at the example test. 

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

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

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

test('get started link', async ({ page }) => {
  await page.goto('https://playwright.dev/');

  // 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();
});
```


On line 1 we import the ‘test’ and ‘expect’ functions from playwright. 

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

On line 3 we define a test by specifying the name and the test function. The test function is given a page that we will use to perform actions and assert expectations. This page is like an incognito tab in a browser, fully isolated, so tests will never interfere with each other.

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

You can interact with the page just like a user would. For example, you can fill in text fields, click links and buttons and navigate to URLS. Each test has a test timeout of 30 seconds . If your actions take longer than that Playwright will stop the test and show an error. You can adjust the timeout according to your needs.

If you were manually testing your application the first thing you would do is open a browser window and type in the URL that you want to test. When testing with Playwright you don’t need to setup or tell Playwright to open a browser as this is built into the test runner. 

To go to the URL that we want to test we call the `page.goto` method passing in the URL. This method waits for the page to load the URL, including all dependent resources such as stylesheets, scripts, iframes and images. This means the page is now ready to be interacted with.

```js
await page.goto('https://playwright.dev/');
```

Note the use of the `await` word at the start of line 4. This is important as Playwright is async and if we don’t use the await keyword then Playwright won’t wait for the page to be ready, leaving you with the possibility of flaky tests.

One line 7 we want to assert the title of the page. Playwright provides a `toHaveTitle` assertion just for this. This assertions will internally retry again and again until the title is as expected or the default timeout of 5 seconds is reached. Since this is asynchronous, awaiting this is essential at the beginning of line 7. Playwright has many more assertions so [check out the docs](https://playwright.dev/docs/test-assertions) for a full list of assertions for your testing use case.

```js
await expect(page).toHaveTitle(/Playwright/);
```

On line 10 we define a new test passing in a different name to our first test. Remember each test has its own page ensuring our tests run in complete isolation. Our second test knows nothing about what happened in the first test.

```js
test('get started link', async ({ page }) => {
});
```

Therefore, on line 11 we need to use the `page.goto` method just like in our previous test to go to the URL we want to test against. 

```js
await page.goto('https://playwright.dev/');

```

When manually testing we use our eyes to find an element on the page and then use a mouse to click the element to interact with it. With Playwright we use locators to help us locate elements on the page followed by the action we wish to perform on the element. Playwright comes with [built in locators](https://playwright.dev/docs/locators) complete with auto-waiting and retry-ability, meaning Playwright will wait for the element to appear on the page and will keep trying to interact with it until it becomes actionable or until the max timeout is reached.

There are many ways to locate an element on a page and to make tests resilient we highly recommend using user facing attributes such as locating an element by its accessible role, or by its placeholder or label name, alt text, title, or text. We highly discourage locating elements by CSS or XPath as they are not user facing, as in it is not something the user sees or cares about. Playwright also supports Test ids if you need that approach.

On line 14 of our test, we use a role-based locator, `getByRole`, and pass in the type of role and the accessible name. 

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

Our test would not be a real test without an assertion so on line 17 we make an assertion to check a heading element with the text ‘Installation’ is visible on the page.

```js
await expect(page.getByRole('heading', { name: 'Installation' })).toBeVisible();
```

In this post we installed Playwright and saw how locators and assertions are used when writing tests. In the next post we will learn how to run our tests with and without a browser window as well as see a step by step recording of the test execution.

## Check out the Video

{% embed https://youtu.be/JdMkZUePkSE %}

## Useful Links

- [Playwright docs](https://playwright.dev/docs/getting-started-vscode)
- Join our [Discord server](https://aka.ms/playwright/discord)
- Subscribe to the [Playwright YouTube channel](https://www.youtube.com/@Playwrightdev)