Playwright Fixtures for Testing
00:00 So we're going to be making our own test object. So I'm going to alias this as base. I said object. It actually is a function with object properties, like expect. So we're also going to remove expect here. And then we're going to say test.extend, or base,
00:18 base.extend. And that is going to allow us to get our own test function. And test will also have the expect function as well. So we can get expect from our own test function. And so then we're going to specify this object.
00:37 And these are going to be all the fixtures that we have. This works out better if you specify the types for those fixtures first. And so here for this type, we're going to say we're going to have an insert new user. And this is going to be a function that
00:53 will return a promise that resolves to our user. So that's actually not what the function itself does, but that's what the return value of the use will be. So we'll look at that. It is kind of an awkward API, I'll be honest. But we're basically just going to return the user object
01:13 that we create in the database. So id of string, the name is string or null, and the username is string. OK, so with that then, we can say insert new user. And this is going to be an async function that accepts an object that we're destructuring here and then use.
01:30 Now, this is super weird that we're destructuring in here. But what you get out of this object is all of the same stuff that you would get out of a regular test. So whatever you're basing this fixture on, all the fixtures that that has, we kind of inherit from those fixtures. So that's what's going on right here.
01:48 And it's kind of weird because we don't actually need those things. But we do have to specify destructuring here. I even tried going underscore. Playwright is not having it. You have to use the destructuring syntax. I don't get it. It's kind of strange, but it is what it is.
02:07 So we don't need any of these arguments, but we're going to add that destructuring syntax. And then we'll have the use function here. And the use function is where you say, OK, when somebody uses this fixture, this is the thing that needs to be executed at that point.
02:26 So the thing that needs to be executed is all of this stuff. So we'll move this up into there. And this is going to be async because we've got our await right there. And then this is complaining at us because we're not returning the proper type that we defined up here. So let's return the new user.
02:45 And there we go. So now we can say insert new user. And we can get our new user from await insert new user. And we have just done what I like to say a overly complicated refactor. So we haven't actually changed any behavior here.
03:04 We have made it maybe sort of like kind of easier to have an insert new user. It's like this roundabout weird abstraction thing going on. But this will behave exactly as it did before. So if I hit play, then this fails. But we do get another user added. So the functionality is there.
03:23 Now our job is just to make sure that we're saving the user ID that is created and then deleting that user ID. So we're going to say user ID, which is a string or undefined as it is at this point.
03:39 And then after our test is done is when this use promise is going to be resolved. And so this function will be executed at the start of our test when our insert new user is executed. And then when the test is all finished,
03:58 then everything that happened that we have after this await right here is going to be executed. And so we can say, well, now that the test is done, let's await. Oh, actually, yeah, thanks. We'll add the if statement there too. So if the user ID is defined, then we'll await Prisma user delete where that ID matches.
04:18 And so that means we can get rid of this. And of course, we need to assign that user ID. So let's assign that right here. User ID equals the new user dot ID. And now we've got this many users. If we run this again, then again, of course, it fails.
04:35 But if I refresh the page, we don't have those users anymore because that user is now getting deleted. And now, of course, the real test. Does the thing still work? Let's hit Play on this. And it does indeed still work. Huzzah. We're in a good place now.
04:51 So like I said, a little bit of a kind of strange API. So we have this base dot extend. This base is just an alias of the test that we get from Playwright test. And that gives us a new test from which we can derive the expect.
05:08 And we define the types for our fixtures that we're going to create. So this is insert new user. And when people use it, then it will return, or it will be a function that returns a promise that resolves to a user ID, name, and username.
05:25 And then we define how we retrieve our fixture via this insert new user. That's going to be an async function. We're going to take what other fixtures from the base. Normally, you actually do use this, but not always.
05:42 But you do have to specify the destructuring syntax. And then we can accept this use function. We define our user ID right here to make sure that we're storing that, whatever user ends up getting created. And then we are going to await use. And this is the stuff that's going
06:00 to be executed at the time our insert new user function is invoked. And so then we will create that user. We're going to hang on to the new user ID. And then when the test is finished is when this promise gets resolved. And so once that happens, then we can check if the user ID was, in fact, assigned.
06:19 And if it was, then we will delete that user that was created. And that is playwright fixtures. Awesome job.