Transcript
00:00 From this moment onward, we're gonna be working with and testing the actual application, the Epic Notes app. If you take a look at the file tree in the Playground directory, you can already see all these different folders, all the source code for the app from the React components to Prisma schemas and so forth. We're not really interested in all of that as much as we're interested in how the introduction of a whole app affects our playwright setup. So let's open the playwright config dot yes and take a look at what changed here. So first of all, I've added a test dir option that points to test slash end to end.
00:34 This is so playwright doesn't run other tests like unit tests or integration tests by mistake. So I'm keeping all my end to end tests in this directory. Then I have a global time out for all the tests which is fifteen seconds. I have a time out for individual expect statements which is five seconds. Then I've added the retries option to have two retries on c I and more importantly this use object over here that provides base URL which is the URL of the running app and this will be important a little later in this exercise as well as the trace option that we're gonna talk about in more detail in another section.
01:09 Now the only thing that's missing is for Playwright to actually run the app, so whenever the tests run we are guaranteed that there is already an instance of the app ready to be interacted with. To do that I will head to the end of the config and add a new property called web server. This property allows you to describe what web server's playwright should spawn before the tests run. So here we're gonna have one test server with the following options. So the first option I need to provide is the command to spawn this server.
01:38 In here you would normally use something like npm start, but this usually starts the production version of your app so it has to be built. And I don't wanna build my app as a part of the playwright setup because I wanna have a designated step for that on CI. Maybe I wanna cache the build artifacts and just have more control over them. So what I'm gonna do, I'm gonna make this command conditional. So I will say if we are on CI, then start an already built app.
02:03 If we are not, let's run the development command npm run dev, the same command we used to develop the application. Now Playwright will run this command and then it will expect a web server to appear at either port or URL. I will use the port option because I already have the port variable over here declared, so 3,000 by default or from the port variable on the environment, and I will make sure to cust it to number so playwright understands it correctly. The next option I will specify is an important one, it's called reuse existing server, and I will set it to true. This option is telling Playwright that if there is already application running at this port, just reuse it, don't run this command again.
02:44 This will be really handy when I am already developing an app and I have its dev instance running on my machine so when I run the tests they will be running against that existing app instance. Then a few quality of life improvements I will pipe s t d out and s t d error from this command that spawns the app and basically the app process itself to the same process that runs the tests. This way, I'll be able to observe any logs, warnings, or errors that my app runtime prints during the test run. This can help a lot during debugging failing tests. And now lastly, I will add the environment object over here and provide here the port which is the same variable that I am waiting the app on.
03:25 This will make sure that the application starts at this port and also set the node environment variable to test just to differentiate the, you know, the test environment inside the app if I ever need to introduce some special setup. So now with these changes, Playwright is gonna run this command before the tests start, npm start on ci and npm run dev otherwise, it will wait for the app to appear at this port, reusing the already running and existing application, during development for example, piping errors and output of that respond process, and also providing this environment variables to the application itself. Now that the configuration is ready it's time to complete the end to end test that will run against my application. So I will head to tests over here and to end and I have a homepage. Test.
04:13 Ts that I need to finish. So here I will declare a test case that displays the welcome heading. And I will continue with it here. First, I will grab the page object from destructor in the context and navigate using page. Go to to the home page which is just slash.
04:31 And notice that I am not providing an absolute URL here anymore, that is because in the Playwright config here, the use option and its base URL option is set to the URL of the running app. And so any relative URLs I provide to go to will be automatically resolved against this base URL. That's really handy. So now that I'm on the home page, I want to find the heading that the epic notes displays and make sure that it's visible. A very simple test similar to the one we did for epic web.
04:59 So I will do page dot get by role heading, the accessible name that says the epic stack. And I will create a assertion around it. So I'll expect this element to be visible. I believe that's about everything, I'm just gonna delete the rest of the instructions. So now that I have this test written it's time to run it.
05:21 In my terminal I will run the same command npm run test end to end, but now playwright, you see the playwright is already spawning my application, I can see these logs, and then it starts the test run interacting with the page. Going to the home page, which I can see here in the loader, and then ascertain that the element is visible and confirming that the test case is passing. Now it's a good time to talk about the Playwright's architecture and how it makes your end to end test runs possible. Let's take a look at this schematic where I still have the architecture of Vitast. But you know what?
05:52 It's not actually that different. Playwright also has the main process that does the test collection and runs them and reports the results to you. It has the workers that spawn your test files to make the runs more performant and provision proper isolation. Of course, both of these run-in Node. Js, so let's just annotate them as such.
06:11 And there isn't really any need to configure the environment here, so you just run the tests. And the obvious change here from vTest is that in Playwright you now also have a whole browser process. So let's call it Browser. Over here. And so we have this browser process that runs our tests, only it doesn't.
06:30 As I mentioned before, you still write and run your tests in Node. Js, but somehow they instruct the browser what to do, right? With things like page dot go to to trigger navigation. To make that possible, Playwright introduces a bridge between the Node. Js process and the browser process, and through that bridge it can communicate between the two, for example instructing the browser automation what to do.
06:52 And that is an important distinction and the reason why in your Playwright tests you're running in Node. Js and cannot access things like DOM APIs, but you can use Node. Js APIs like reading from file system or spawning an HTTP server. That is a crucial distinction from something like VITA's browser mode where your tests run-in the browser and have full access to browser APIs, but they have an opposite limitation not being able to control anything Node. Js related.
07:18 That is also the reason why whenever you want to instruct the browser to do something you usually use this bridge over here through some of the APIs that Playwright provides, for example the page object.
