First steps with end-to-end testing using jest + playwright (puppeteer)
Przemysław Paczoski
Posted on December 3, 2020
Oryginally posted at: https://kodziak.com/blog/first-steps-with-e2e-testing-using-jest-playwright
This post is a continuation of the “First steps with test automation” article.
Recently I wrote a post about my first steps with test automation. I tried to answer questions related to the topic and guide you where and what to search for (if you're interested - click here!). Now, I want to expand on it with technical steps you need to take and show you how easily you can create a basic test with a real world example (my blog 🥳).
We will create a base repository with Playwright and JestJS and write a basic test which will:
- Load the blog page,
- Check if the blog title contains the author’s name,
- Check if the posts list isn't empty,
- Click on the first post title and check if it loaded correctly.
To achieve it, I think you need a little more knowledge, so I split the article into three topics (+bonus):
- What do I need to start with automation?
- Project setup with Playwright and JestJS
- Let's write an automated test
- Bonus: Test recorder!
Before starting the game, here are some topics which you should be familiar with:
- Basic knowledge of JavaScript,
- You know how to use CLI and NPM/Yarn,
- You're familiar with HTML/CSS.
What do I need to start with automatization?
First of all, you need a library/tool which allows you to control a browser using code. Today, I'll use NodeJS library called Playwright (which is very similar to Puppeteer – here you can find a nice article about the differences: https://blog.logrocket.com/playwright-vs-puppeteer/) to automate our actions with an API. You need a tool like this to write tests that will imitate the behaviour of end user (behave like our clients).
Basically, doing a test manually, you're using a mouse to click and scroll or a keyboard to fill in the forms. In automated tests, you're using a library API to do the same things but the browser is controlled by automation software, not a user.
Next, we need assertions. Playwright provides their own ones, but honestly – I've never used them. I like JestJS, which, besides that, is a test runner, which gives you more opportunities to control the whole test base. With an easy way to do parallelisation or configs for dev/production envs, writing tests is only a pleasure 🥰.
In summary, you need:
- A library to control a browser → we'll use Playwright,
- A test runner → we'll use JestJS
Project setup with Playwright and JestJS
So we will use:
And if you decided to stick with puppeteer:
Note: When using puppeteer, you need to change selectors because the API is slighty different. In our basic test, it is enough to remove css=
part and change waitForLoadState
⇒ waitForNavigation
. After those two changes, everything should work.
Before we start writing our first automated test, we need to set up the repository:
Let's initialize it first:
-
yarn init
ornpm install
git init
Then install the required dependencies:
yarn install jest jest-playwright-preset playwright
or
npm install jest jest-playwright-preset playwright
And create two config files,
// jest.config.js
module.exports = {
preset: 'jest-playwright-preset',
}
// jest-playwright.config.js
module.exports = {
// Describe which browsers we want to run
browsers: ['chromium', 'firefox', 'webkit'],
launchOptions: {
// If we want to run browsers in headless mode or not,
headless: false,
// If we want to have opened devtools from start
devtools: false,
}
}
Also, we need to an execute script to our package.json
:
"scripts": {
"test": "jest"
},
Now, you can yarn test
or npm run test
which will run all files matching *.test.js
names – but we don't have any tests yet 🙈
One more thing that I added is tests/
directory where we will store our test.
Let's write an automated test
First we need to know what we want to test 🙈
I created a basic flow relating to my blog, which you're reading now:
- Check if the blog title contains the author’s name,
- Check if the posts list isn't empty,
- Click on the first post title and check if it loaded correctly.
In the directory tests/
I added a file example.test.js
. And to make it easier for you, I coded the above scenario, adding comments line by line, describing what’s happening.
let blogPosts = [];
describe('Blog - kodziak.com/blog/', () => {
// Will trigger methods before tests
beforeAll(async () => {
// Load blog page
await page.goto('https://kodziak.com/blog/');
})
test('title should be "Blog | Przemysław Paczoski"', async () => {
// Get website title
const title = await page.title();
// Compare title of current page
expect(title).toBe('Blog | Przemysław Paczoski');
})
test('should display list of blog posts', async () => {
// Get all blog posts as an array of objects
blogPosts = await page.$$eval('css=.post', elems => elems.map(el => {
return {
title: el.querySelector('.post-title').textContent.trim(),
description: el.querySelector('.post-description').textContent.trim(),
href: el.href,
}
}));
// Check if list length is greater than 0
expect(blogPosts.length).toBeGreaterThan(0);
})
test('click on blog post should redirect to article', async () => {
// Go to first blog post, there we're waiting to resolve all promises from array
await Promise.all([
// Click oo .post-title css class element
page.click('css=.post-title'),
// Wait for networkidle event, promise resolves after event
page.waitForLoadState('networkidle')
]);
// Get title, content and href of current article
const [articleTitle, articleContent, articleHref] = await Promise.all([
// Get article title, we use here array destructuring
page.$eval('css=h2', el => el.textContent.trim()),
// Get article content
page.$eval('css=.content', el => el.textContent),
// Get article href
page.url()
]);
// Destructuring first element from an blog posts array. First we use array destructuring and then object destructuring
const [{title, description, href}] = blogPosts;
// Compare title from posts list with current article's title
expect(title).toBe(articleTitle);
// Check if the current article content includes description from posts list, compare output with boolean true
expect(articleContent.includes(description)).toBe(true);
// Compare href from posts list with current article's href
expect(href).toBe(articleHref);
})
})
After we finish coding our test, let's run it using the command yarn test
.
Playwright will open three browsers which we described earlier: chromium
, firefox
, webkit
.
And if everything goes well, we should see the following log:
And that's it! We ran our tests positively in three different browsers.
Bonus: Test recorder!
Lastly, a good way to start with test automation could be to use test recorders. Nice one, created with playwright is: https://github.com/microsoft/playwright-cli which allows you to record your browser interactions and automatically generate a fully working code – an automated test with Playwright.
Conclusion
In this article, I wanted to show you how easy it is to automate a basic test scenario using tools such as Playwright and JestJS. I hope that will be a good start for you to explore this part of software engineering.
After reading it, you should have learned:
- What Playwright (Puppeteer) and JestJS are used for,
- How to set up a repository using those technologies,
- How to write a basic test.
Fully working, implemented code from this article can be found in my repository: https://github.com/Kodziak/playwright-first-steps
Have a nice day!
Posted on December 3, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.