Authentication in Database Integration Tests
00:00 So now we're going to delete this fake user, create fake user stuff, and instead we're going to create a new user using the insert user. So here's our user equals await insert new user from the dbutils, and our setup function is already handling deleting that user, so that works out nicely for us.
00:18 And then we need to get a image so that we can add an image to this user, because that's part of what we're testing is that they have an image. So let's first grab user images from await, get user images from our dbutils,
00:37 and then we can grab a user image. You could just take the first one if you want. Yeah, random element, yeah, that's deprecated. Thanks anyway, Copilot. Or we can say user images. What I do is I say faker.random number, and yeah, that also deprecated. Thanks a lot.
00:57 And then I say number.int with a min of zero and a max of the user images.length minus one. So that way we can add some randomness to this and kind of communicate that the actual image itself doesn't matter, like there's no special image
01:14 in this get user images array that we get back. It's just any one of those images will do. And so now we can use that to update our user. So let's await prisma.user.update, and where the ID is the user.id,
01:32 and the data image create user image. All right, so now, here, let's bring in Prisma properly. There we go. So, and we're conflicting with this user, so let's get rid of that user. And so now the user that we're referencing in here is going to be an actual user in the actual database.
01:52 And so instead of using this loader right here, we can use the real loader. Oh, snap. And we can replace it with the real one. Now this is complaining because if we take a look at our loader import up here, we're importing the type. Well, now we want more than just a type. We want the full thing, my friend, full thing.
02:09 And now we're going to get coverage not only on our UI, but also on the loader itself. And I think that first test is going to pass. Yeah, look at that thing. I'm so proud of you. Well done, test. Okay, so our second test needs a lot of the same treatment, but it's a little bit more complicated too.
02:27 So let's grab this stuff, same sort of stuff, but now we have to make this authenticated. We got to authenticate the request that's going to come into our root loader. So here, let's update this loader right here. This can be the root loader.
02:44 And again, we are importing that as a type right now. Root loader, where is it? Right there. So not the type anymore. Yeah, now we're talking. And then this loader can be the actual loader as well. So awesome. But we've got a little bit of a problem here. So things look okay here,
03:07 but we need to do a little bit of extra work on the root loader here to make it so that we can authenticate this request. So if we dive into the root loader, we've got this request object right here, and we're going to get the user ID from that request object. Well, the problem is that we're just passing the loader directly. We don't actually get to control that request object.
03:25 That's createRemixStub is going to create that request object. And so we need to somehow modify the request object that createRemixStub creates and so that we can create that authenticated cookie value. So let's create the cookie value first,
03:42 and then we can go into actually how we're going to pass that cookie value to the request. So we're going to get a cookie session from awaitSessionStorage.getSession. Oh, that didn't import. There we go, session, there we go.
04:01 And then we'll get, or set our cookie session set with the session key to our session.id. Oh, we need to have a session. So let's await, or our const session is awaitPrismaSession
04:16 createData, expirationDate is getSessionExpirationDate. There it is. And userID is user.id. Awesome. And let's select just the ID true. And that is all we need for setting that in the session.
04:34 And then we got the setCookie header from awaitSessionStorage.commitSession with the cookie session. And then we have to parse it. So our parsedCookie, setCookieParser, whoop. Yeah, setCookieParser, come on. Copilot, there it is.
04:54 All right, and that setCookieParser is going to come from this import right here. Awesome. And then our, with that parsedCookie, we need to get the, turn that into a cookie header. And yeah, that is going to do it actually. So to string. And now we've got our cookie header that we can apply to our requests.
05:17 Solid. Okay, so here's the trick. What we're going to do is we're going to take the args and we're going to say args.request.headers, setCookieHeader, and then pass those on and return that. That's it. And we are set.
05:37 We'll do the same thing over here. And this is not going to be the root loader, but the regular loader. And now we're all set. So that is how we can kind of augment what is passed to our loaders and still be able to use the underlying loader. And we get a passing test. It's amazing. So there you go.
06:00 That is awesome. So let's just review and then we can be done with this. And like, this is so cool, right? Because we're doing a lower than end-to-end level test, but on a specific route. And we're covering not only the UI, but also the loader. And we could do the same with the action.
06:19 That is so awesome. And like, there's very minimal mocking going on here, just third-party stuff is being mocked. And so that's why I'd consider this an integration test, because we're actually like talking to the database and stuff. Super, super cool. Okay, so we insert the user. We update the user to have an image because that's important for this particular test.
06:38 And yeah, then this insert new user tracks the users that are created. And we have our setup file that's got the after each that deletes the users from the database that were created. So we're cleaning up after ourselves and it's awesome. And then over here, we do the same thing, but then we also create a session and then this should actually be pretty familiar. We've done this a couple of times.
06:58 It seems like maybe a utility is a useful thing for us to do at some point. But yeah, create the cookie session, set cookie header after we set the session ID and parse that and then get the cookie header out of that. And then we can set that cookie header on the request.
07:17 And now we're authenticated and everything will work and it's awesome. So great job on this one. I know there was quite a bit going on, but I think you did well. So pat yourself on the back. Well done.