All right, I've been talking for awhile. So I'm gonna catch up on the chat. Lucas said this is probably also true for Knock and Mock Serviceworker. But I've been talking for a while since I decided to see what that is in context of. Jorii asked a question about functions from Hooks. Jorii, I will try to catch up with you in the next break cause that's a little bit unrelated. I can give you some detail there. Why would you use Mock Serviceworker from component testing? Super developer experience. Polyus asked, why would you use Mock Serviceworker for component testing? You might do that if you are doing component testing but you're testing a lot of your components together. Now React Testing Library actually encourages, hey, when you have a component, you have a high-level component, maybe it's a whole screen or a whole page component, it will, by default, put all the child components and all the things they integrate within there. And so maybe you wanna test a lot of your components in integration. Maybe you're not able to use something like Cypress or Playwright for end-to-end testing, or maybe you just prefer it. That actually helps me in React Native as well because end-to-end testing is challenging in React Native and so I like to do component testing of a lot of things together. One of the other things though, if you're using Mock Serviceworker or Nock, is that they're APIs because they're HTTP-specific, allowing you to attach this part and this part together. So you can expressively say, when the user hits this endpoint, return this data, and so they're just a bit more targeted for this scenario. So that's some of the benefit. Cool. If you have two get calls, should we do api.get? Yeah, so Mariana asking if you have two get calls, how can you mock different things? Yes, yeah, like and so Rian replied about mocking the implementation, checking what was passed to get and replying with different data, and so that's helpful. And that's actually another case that Nock and Mock Serviceworker can help because they're set up to mock different data for different endpoints, even if you have the same function called to dot get, they make it easier to mock different data for those. Dominic says, how can we delay the promise to test the loading state? So a trick that I use for that is a promise that doesn't resolve, doesn't settle. So if you all, you know, usually we don't actually build promises ourselves. Usually they're given to us by third party APIs. But you could say api.getMockReturnValue. So we're mocking the return promise, you can say new promise. And if you don't, you know, a promise receives a resolve and reject, and you're supposed to call that at some point in here. But if you just don't call it, this is a promise that never settles. And that actually doesn't cause memory leaks, I don't think, or doesn't cause any problems with just tests. But this would just give you an indefinite loading state. And so that way you're sure it's never going to resolve, you're sure you're not going to have timing issues, and you won't get that act warning about something changed later. So yeah, creating promises that don't settle is a great way to test loading states. Does it wait before a screen find by text works similar to waitFor? Yes. I think the find by APIs are newer, and they're recommended. Sometimes you still need a waitFor, or a waitFor element to be removed, which is another API. But if you're just waiting for something to be present, the find by APIs are kind of straightforward. You just type them straight ahead. But yes, as Vlad said, the RTL docs have a lot of detail on that. Cool. All right, let's take it back to the slides, because there's a lot going on with these. So let's recap the information we saw with Jest module mocking. And so let me just to repeat the distinction before, in our last segment, we talked about Jest mock functions, which is when you create a function, like I'm creating a function and I'm passing it in a prop or putting it somewhere. Jest module mock is where you're pulling something in from another module and it's giving you functions. Jest module mocking allows you to intercept that, to turn those into Jest mock functions. Then you can then mock the result value and do assertions on to see how they were called. So to walk through those steps again, the way to do a module mock is you call Jest.mock. This needs, I'm pretty sure this needs to be at the very top level of your test file outside of the describe. So that means for all the tests in this file, that will be mocked out. You pass the path from your test file to get to the module that you're mocking. That does work for third parties as well. So if you're using like Axios directly, you can just pass Axios in there. Just whatever the form you're importing from, the string you're importing from in your production code, in your component, you pass to Jest.mock. Then assuming you probably need access to those mock functions in your test, you import them in your test file using the same import you'd use in the component. And from there, you can call JestMockFunction APIs. You can mock a resolved value, which is what you'll commonly use when you're doing API calls and stuff like that. But if it's a synchronous thing, you can just mock a return value. If you check the JestMockFunction APIs, you'll see all the options available there. And in the case of here where we're testing data loading, or waiting for this to come on the screen, for the first one, we use a wait find by to make sure it has time, to allow for the asynchronous speed that happens for the fact that we're getting a promise back from a web service called. But notice, it was, well, let me show you the speed, just to kind of interrupt myself real quick. Hit return, and this comebacks right away. So it's not waiting five seconds or one second before it even checks to see if it returns. It's coming back very quickly. But just the find by gives it a few seconds if it takes up to that amount of time. And then for the extra safety here, we're doing a call, an assertion on the call that was made to the mock function to make sure we pass the right arguments. This is something I see, no matter what technology you're using, we're actually actually using Axios Mock Adapter in my client project, but it's very tempting for us. You know, when you write your component code first, and then you write your test, and it's big component because it's real project. It's not just my trivial example here. And it's like, oh, I'm gonna do so much work to get this working. This is my first test mocking on HTTP requests, or there's just a ton going on in this component. And so you kind of just want to get it passing. And so once it's passing, you tend to want to move on. But remember, we saw in our test that even though the test was passing when I had mocked this result value, we weren't fully confirming the contract. We weren't confirming that that outgoing request had the right URL. So it's always tempting, I mean, so Axios Mock Adapter, you can say, I think what we run into, you do choose the URLs there, but our temptation is not to put it pass in like the query string parameters or the post body to not assert against that. So then we're not actually confirming that we're sending the right data to the server. It opens us up to false positives. So when you're thinking about, I mean, I didn't make a slide for this, but when you're thinking about connecting to web services, remember to confirm what's going out and provide what's going in. If you just do one side or the other, you might be lacking what's needed to get full confidence in what's going on. Yep, and so mock in mock modules, sorry, let me say this again. When you have a mock module, there's functions within it that you're given, those are just mock functions. So you can mock return value. I don't think we saw it before, but you actually know, I don't think these came up before because when we were doing that on send function, we didn't care about what came back, we ignored the return value. We just needed to confirm that the function was called. But when you do have a mock function and you do care about what's returned, or it's a promise that resolves or rejected, then you can use these mock return value, mock resolve value, mock rejected value that allows you to control what comes back to your code from that mock function. Just to kind of visualize those finders we talked about, first in the workshop, we saw these get buys. Those allow you to check for something on the screen and it errors out with helpful JSX output if it isn't found. We saw query buys, and I will say, I don't know how to name these, it's not immediately obvious from looking at the name which one is which, you just kind of get used to it over using RTL over time. But query buy, what it means is, if it's not found, it gives you a null back. So that allows your tests to succeed when you expect there not to be something present. Then there's find buy. And just like with the others, find buy is a prefix and you have all the same suffixes. You have text, all text label texts, et cetera.
Comments