Loading
Current section: Best Practices 7 exercises
solution

Queries

Transcript

00:00 Our happy path test case is passing. But when we're testing components that involve network, we need to make sure to also test different network-related scenarios, like unexpected responses, error responses, or any other business logic-defined scenarios that we have in our app. Like here, we have a second test case that displays a warning when the user

00:19 tries to apply a legacy discount code. We know when the discount code is legacy because the server responds with a JSON response that contains is legacy key set to true. So in this case, we need to intercept the same request, but handle it differently. To do that, we will use what is called the runtime request handler. First, let's grab this worker instance

00:39 that we prepared here. And now let's attach an overwrite. We will call worker.use and provide any request handlers that should take precedence for this test. Let's define the same handler for the post request, use the same URL that we have. But in the second function, in the resolver function, let's handle this request differently.

00:59 We will still return a mocked JSON response, but we will provide a different response structure. Let's read the request body once again here, create a code variable and read request.text. So we have the code value here. For the amount, let's provide, let's provide 10, I think that'll be okay.

01:18 And the legacy, let's provide true. So this will make sure that in the context of this particular test case, MSW handles this matching request with a different response. This response is different from the same happy path handler that we have in handlers.ts. So what we have to do now is to write assertions around this behavior.

01:37 So first, let's make sure that these legacy codes are still applied, which means they're visible to the user. There's a confirmation. Let's write an assertion for that. Expand the element with text, nope, with text. And this will be the text here. The discount we provided and the discount amount

01:57 that we provided here from the response. And we want this element to be visible on the page. But there's another expectation here. When legacy discount codes are applied, there has to be a warning that lets the user know that they applied a legacy code. So let's write assertion for that too.

02:15 And to write this expectation correctly, let's take a look how this warning is displayed in our component. Let's go to this front component and find this scenario. I think it is here. So when there is a notification to display, we have a paragraph with the role alert and the text, whichever text we basically have

02:34 based on the response from the server. So let's select this element as well. Expect element page get by role alert. And since it's a paragraph, it doesn't have an accessible name. So instead, we will count that there is a single alert on the page and just assert that it has a text content

02:52 that equals the warning message that we expect. So in this case, it's this message. So what we did here, we applied a request handler overwrite that handles this request with a different response. This allows us to tap into different logical branch for testing this component and expect that the legacy codes are applied,

03:12 but also that the warning is displayed for the user. And in a very similar manner, let's complete another test case for an error. Basically, we need to make sure that our component is able to handle network errors when applying the discount code fails. Just in the same way, let's access the worker here in the fixture, applied an overwrite worker.use,

03:33 intercept the same request. I'm going to copy this handler. So over here, and instead of responding with a successful response, we will respond with an error response. No need to read the request body anymore. And we will just create a new response instance, provide nobody,

03:50 and set the status code for that response to 500. So whenever this code component tries to submit the code now to this URL, it will always receive the 500 error response. And now the expectations. We need to make sure that the component actually does that handling. It will be the same handling as we did for the warning.

04:09 So let's create another expect element, page gets by role, alerts. But now we will have a different message in that alert to have text content that will say failed to apply the discount code. So again, the principle here is the same.

04:30 For this scenario, provide different network behavior. So component taps into that logical handling and write the expectations that in this case, we communicate to the user that applying discount has failed. Now let's try running this test. So open the terminal, run npm test, and we can see all of our three scenarios passing. And as a cherry on top,

04:50 let me show you how can you reuse the same mocks even when developing the app. If you head to your main module, you can create a function called enable mocking where you will import this worker instance that we prepared here conditionally, for example, only when developing. And then await the worker start promise. This will start the same worker instance

05:09 in the browser when you're developing using the same handlers you provided. And the next thing you have to do is to call this enable mocking function and defer the rendering of your app until that function resolves, until the mocking is ready. By doing this, you eliminate the race conditions between MSW activating the worker and your application potentially making requests,

05:29 for example, on initial render. Being able to reuse the same mocks across different use cases from testing to development to debugging and showcasing your app is really powerful. And I encourage you to utilize that.