Check out a free preview of the full Enterprise UI Development: Testing & Code Quality course

The "Writing Playwright Tests" Lesson is part of the full, Enterprise UI Development: Testing & Code Quality course featured in this preview video. Here's what you'd learn in this lesson:

Steve writes a basic Playwright test that navigates to a URL, types text in an input field, and clicks on one of the results. End-to-end tests like this add confidence in UI behavior and can often eliminate the need for multiple component or unit tests.


Transcript from the "Writing Playwright Tests" Lesson

>> We will make a new test file. I mean, I could write in this one too, but, I do pokemon.spec.ts. Out of the box, it uses spec. Could you change that? You could. Why am I using spec? Because Vitest was looking for test [LAUGH], right? And so by the file name, Playwright will run the spec files, if I just run the test files, and never the twain shall meet.

If you don't like spec and you don't have Vitest, do whatever you want. Change it to whatever makes you happy. That right now makes me fairly happy as we kind of go through and we do our thing. Cool, it's got that base one in there. So I'm gonna spin up my app real quick so we can take a look at it, And make sure it works before I start.

I started testing out but I pulled the wrong repo. So there are a bunch of different apps that you can choose to test. Basically it's got just dumb stuff to play around in, right? This is basically my sample playground. We're not gonna do everything in here, but if you want to try different things, that's why it puts a stupid toast notification that vanishes, all sorts of stuff like that.

As a fun playground, this is my perverse idea of fun. It's got file downloads, it's got everything you could possibly want. It says, input obstacles from before that you can drive and do things with. This is actually the one that has a database and has auth, so you can log in and sign up and analyze the cookie.

So if you want to try out stuff like, again, if we do a full version of this, we can go all the way in, this is the Pokeman search, which is the one I'm gonna try out. And you will also notice that the query param automatically updates, so I could test stuff like that as well.

I have full control over the browser. I don't have to use JS DOM or anything along those lines. I can see stuff, it's like a full on spa. I think some of them are server-side rendered where I can see views within views. You can get facts about dogs, right?

So if you wanna step out different network requests, you can play and put this on, I think you can write to the clipboard. All those things are things you can test in Playwright. Obviously, I'm gonna do all those. My goal today is to show you how you might weaponize this tool to get as much sanity around your gnarly codebase as you possibly can as quickly as possible.

With that, we'll go through writing a test real quick, and then I will show you that for our purposes when it comes to the theme of our time together, we're not gonna write that many tests. And I will show you why I think that for getting sanity around your code base.

I am now thinking that maybe I should just open the workshop with this, but then it would have made everything else less fun. So this feels like a crescendo at the end. Cool, so let's go ahead and look at kinda some of the differences here. Your test and expect, this one come from Playwright test instead of Vitest.

You don't have a describe because it's test.describe does the same thing. We'll grab those and we will do test. It has an input field, input field-
>> Could you use it instead of test here?
>> I don't think so. Yeah, now I know that because I tried that earlier today cuz I expected someone would ask me that question.

There's the things that you just do, and then when you're preparing for these things, what questions are people gonna ask me? Yeah, input field for searching for pokemans. Cool and that's an async function. Also in the other repo, I gave you some code snippets so you never have to do stuff like that.

You could steal them, they are there as a hidden treat in the VS Code directory. It has an input, For pokemans. Awesome, I should have actually called it Pokemans, so I don't get a seasoned letter, but here we are. Awesome, so what will we seek to do here?

Let's write a simple test. And so, first thing we wanna do is, did I put the base URL on? This is one of those things where I'm going where the spirit takes me. Did I set a base? Yeah, I did. Look at me go. Awesome, so we'll start with await page.goto("/pokeman-search").

Right, that's an argument that gets passed in here. There are no globals to speak of. Honestly, for a smoke test, [LAUGH] did your server start up at all, right? Cool, and then we can go ahead, I can run it. We did have that failing test in there intentionally.

That's what was hanging out for those 30 seconds. It's because I literally had that test where I tried to make it fail. So we'll go ahead and get rid of that one. Let's get rid of that file completely. Cool, I wonder if that's why stuff was breaking in here before.

Yeah, okay, cool. This works better if you have more than one monitor. Let's see cuz everything's failing me at this point. But let's take a look. So yeah, you can hover over and get a sense of everything on the page and what the selector is. The other really powerful thing that I absolutely love is, and I wonder cuz I got some weird highlight that will not go away, in this case as well.

I don't care about that anymore, sure. I can do page.getByRole. And I can do input, Or even a button or something like that. One thing, things are being weird for me now, was actually as I was typing earlier, it would highlight the thing in the browser as I was typing it.

So I would get the visual feedback as well. Yeah, I do get my testID search. So let's kind of show what this would look like, page. Yeah, there you can see it, right? I'm just typing and it's highlighting that for me based on where my cursor is in VS Code.

If I have a matching selector, it shows it for me in Chrome. And that I should not be that amused by something that simple and here I am, right? And so I've got that. And it will show it to me. So that integration is super important. What I am trying to kind of iterate towards is showing how we can use this to get a lot of sensibility around stuff.

So just to show you real quick, I can also like, if I grab this, you can see like that works. And you can even see what selector matched it, like a partial match in this case on the placeholder did get it for me. So little changes shouldn't break your test.

Like Playwright, more so than testing library, is built to be somewhat resilient despite the struggle bus that I just rode on for a little bit with the plugin having an errant port running. But for whatever I'm running, I get that visual feedback as I'm moving through the code, what I have and stuff along those lines.

So, for instance, we could do something with whatever one, say, I want. I'm gonna just kinda move this a little bit so we can see. So I've got the search input. I can take that and I can then say, wait, we should do searchInput.type(), and we'll do 'pika'.

And we'll do page.getByRole (), we'll look for a link. And look at the background. If I'm like, what was it again? I get all of the help. The problem is moving my cursor ruins it. You have to trust that on a bigger monitor or two screens, it's pretty dope.

Get role by link, let's make that happen again. Now it's gonna fail me again. We'll do {name: 'pikachu'}. Cool, and do I hit that button again and have it fail me? We'll find out. Yeah, unclear versus a restart. What's gonna happen there? If I have to do that, I will do it quickly so that we can kind of pull this train into the station.

But let's see if I can kinda get to the main point without that, cuz it's one of those things where 60% of the time it works every time. But I probably have some other errant process on some process ID that, other than a restart, nobody wants to watch me find at this point.

But we could also run that test. Actually, I will get an error if I try to run the test, and I want to show you that error. npx playwright test. It is gonna yell at me that something is running on that port, and it's gonna say, hey, if that's cool with you and you don't wanna make sure that we're the only thing on that port, you can have this setting to reuse existing server is true.

I use this a lot because I'm developing, and that's really great for CICD, I spin it up, I wanna run it. But if I have one running just use that one. And so I will do that. We'll pop that setting in here as well. Cool, and now I should be able to run my thing, and it will run it across all of them, and three tests and everything is good, right?

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now