Web Automation with Playwright
Tags: playwright, javascript, automation, webscrapping
Published: 2021-12-26 06:54:05

The use of the internet has grown rapidly with the introduction and growth of the technologies. Billions of people use browsers to surf their internet. To fulfill the needs of the users we developers have to ship extremely rich, interactive and responsive applications.  In addition to human users, there has always been the need to automate the browser. These use cases might include process automation and testing.

Having a good reliable tool for web automation and testing is a real need for developers. In this article we learn everything about [Playwright](https://playwright.dev/) and how it can be used for browser automation, e2e testing and even web scraping. 

#What is Playwright?

Playwright is an open-source web automation tool. Playwright project started as a fork of the [Puppeteer](https://puppeteer.github.io/puppeteer/) project, from former members of the popular puppeteer tool team. It is currently maintained by Microsoft and is supported for Windows, MacOS, Linux, and all browsers.

The goal of Playwright Node.js is to provide a single API to developers and testers to automate their web applications across today’s three major browser engines like Chromium, Firefox and Webkit


>Playwright is a [Node.JS](https://nodejs.org/en/) library (by Microsoft) to automate > [Chromium] (https://www.chromium.org/Home), [Firefox] (https://www.mozilla.org/en-US/firefox/new/) and [WebKit] (https://webkit.org/) with a single API. Playwright >is built to enable cross-browser web automation that is ever-green, capable, reliable and fast.

Moreover, Playwright supports various programming languages such as Node.js, Python, Java, and .NET. You can write the code that opens websites and interacts with them using any of these languages.

#Why Playwright?

Playwright at its core is built to solve the common challenges we face while automating which are slowness of test execution, unreliable wait scenarios, the need to write a lot of boiler-plate code for browser setup, and parallel execution, etc. The playwright tries to address these issues and makes test authoring more readable, fast and reliable.
Here are some of the key strength of Playwrite

- Playwright is dead simple to set up. Once we download the binaries for all the supported browsers from npm, which can be done with a single command npm i playwright, you are all set to go.

- Cross browser support on the fly. It supports three core browser engines like Chromium, Firefox and Webkit. So, the test can be written once and executed in all the browsers with no/minimal configuration needed.

- Playwright works in 3 of its principles at its core Browser, Context, Page.

Browser: The first thing we need to run a test is to launch the browser. The playwright does this using the object of browser class which is nothing but simply an instance of Chromium, Firefox or Webkit.

Context: Playwright achieves parallelization through browser contexts. In the playwright’s term “Browser Context is an isolated incognito-alike session within a browser instance”.

Page: It’s a new tab or a popup window within a context. Every action the test will perform will be on this object.

- Auto waiting and reliable execution. We have the feature of auto waiting for UI elements to be available before interacting with it. This makes the test simple and avoids the extra steps of adding explicit waits. If we need, we still have the custom wait unless the selector is available on the screen.

- Authentication session storage is built in. With playwright we can store the authenticated session details or cookie inside a context. Once this is stored it can be used across all tests within that context and prevents the need for multiple logins.

- It supports major programming languages like Javascript, Python, C#, Java and its much faster performance than Selenium.

# Let's automate a twitter like

Firstly we need to make sure we have Node installed in our machine. After you have verified installation lets create a new simple project and call it playwright-automation with following commands inside your directory path

```sh
mkdir playwright-automation
cd playwright-automation
npm init -y
npm i playwright
```

We have now added the above commands. We have successfully created a project, navigated into it and initialized our package.json file and lastly installed playwright library. After this is done, let's start writing our code in a brand new file and call it main.js which can be created with the command below.

```bash
touch main.js
```

Now, let's make our automation interesting. We will login into twitter and add a like to the top post in the main page. 

Let’s import chromium from Playwright.


```javascript
const { chromium } = require('playwright');
```

Then we can launch the browser and create a new page instance.

```javascript
const browser = await chromium.launch({ headless: false });
const context = await browser.newContext();
const page = await context.newPage();
```

Let’s take a look at the provided code – the first line of the code imports Playwright. From there the context is instantiated. It provides a way to operate multiple independent browser sessions. And from the context, the page is instantiated. All of them with the same await pattern as all of these functions return Promises. Then, an instance of Chromium is launched. It allows the script to automate Chromium. Also, note that this script is running with a visible UI. We did it by passing headless:false. Then, a new browser page is opened.

```javascript
(async () => {
 const browser = await chromium.launch({ headless: false });
 const context = await browser.newContext();
 const page = await context.newPage();
 await page.goto('https://twitter.com/i/flow/login', {
   waitUntil: 'networkidle',
 });
// rest of code
})();
```

We wrapped our function in an async function as playwright is asynchronous and returns Promise objects. By standard they use the async-await pattern which is why you see all code encapsulated in an async function.

We have used .goto method which takes in the URL to navigate and second optional parameter of options which you can find in more detail [here](https://playwright.dev/docs/api/class-page#page-goto)

Let’s enter an email and password so that we can authenticate our Twitter account. We can achieve this using the page.fill(selector, value[options]) method which waits for an element matching selector, waits for actionability checks, focuses the element, fills it and triggers an input event after filling. Note that you can pass an empty string to clear the input field. Since I did not see a unique DOM queryselector for the Next button as shown in image below, we will use the keyboard to interact with our chromium browser.

![Twitter login screenshot](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/es8bbsw8e8syc28bdm46.png)

```javascript
await page.fill('input[type="text"]', 'user name');
await page.keyboard.press('Tab');
await page.keyboard.press('Enter');
await page.fill('input[type="password"]', 'your password');
await page.click('div[data-testid="LoginForm_Login_Button"]');
await page.waitForNavigation();
```

In the snippet above we have completed all interaction needed for our authentication to happen and lastly we used a method waitForNavigation() method which is generally used after clicking on an element could trigger asynchronous processing before initiating the navigation.Lastly, let's make a click to a post there in default the top post in the top.


```javascript
 page.click('div[data-testid="like"]');
 await page.waitForTimeout(2000); // wait for 2 seconds
 await browser.close();
```

If you have noticed, the data-testid attribute is usually added in by javascript developers to specifically allow automation tools to navigate through applications, because react usually auto generated ID’s, however these are usually scrubbed before an app goes to production. We can now run our script with the command below in our terminal.

```bash
node main.js
```

Yes, we have actually made a like to a tweet listed on top of the page. Our final snippet of code would look something like

```javascript
const { chromium } = require('playwright');
(async () => {
  const browser = await chromium.launch({ headless: false });
  const context = await browser.newContext();
  const page = await context.newPage();
  await page.goto('https://twitter.com/login', {
    waitUntil: 'networkidle',
  });
  await page.fill('input[type="text"]', 'user name');
  await page.keyboard.press('Tab');
  await page.keyboard.press('Enter');
  await page.fill('input[type="password"]', 'password');
  await page.click('div[data-testid="LoginForm_Login_Button"]');
  await page.waitForNavigation();
  page.click('div[data-testid="like"]');
  await page.waitForTimeout(1000); // wait for 1 seconds
  await browser.close();
})();
```

#Conclusion

Playwright is an amazing framework to explore and the latest version released till date when this article was written is v1.17. Due to its asynchronous nature and cross-browser support, it’s a popular alternative to other tools like Selenium or Puppeteer. It’s a Node.js library and built for a highly reactive modern web application, which makes tests written using this framework, faster, capable and reliable. 

Most importantly, it can extract text that is rendered dynamically. It can also help us to navigate to URLs, enter text, click buttons, etc. It also does support screen recording as well.  Some of these things can also be done by other tools such as Puppeteer and Selenium, but if you need to work with multiple browsers, or if you need to work with language other than JavaScript/Node.js, then Playwright would be a great pick.  

If you are interested in digging deeper into Playwright, please take a look into its official documentation [here](https://playwright.dev/docs/intro).

Thank you.

Happy Coding 💻