Frontend is mostly about displaying and fetching data from the backend using API.
The web application is based on a client-server model. The client issues are mostly data-related - invalid API calls, error handling, unexpected response, etc.
API mocking allows developers to model an exact API interaction that causes an issue.
Why mock API?
If you want to test data, you can hardcode and test it.
But API involves network communication.
That means your app is interacting with the network, and when you hardcode the date, you don't test the network aspect of your app.
That's why we mock API(simulating like a real word scenario to test your app)
How network and its data from API are simulated?
Your app should send a request to the network.
But it should not hit the backend because every API call costs you and is time-consuming.
We will intercept the request and give the app the required response.
Since this interception happens outside the app, the app doesn't know about this and thinks this comes from the actual backend.
How to intercept?
Welcome to Service Workers!
A service worker is a type of JavaScript file that runs in the background of a web page, separate from the main thread.
It acts as a middleman between the web page and the network.
It intercepts network requests and allows you to modify or respond to them in various ways.
They are used in offline support, allowing users to access previously viewed content, caching, and performance enhancement by reducing the number of requests to load the content.
Mock Service Worker(MSW) library:
We need to install this library to mock api's and test.
'MSW' leverages service workers designed to intercept the request on the network level.
With 'MSW', we create some miniature server that handles the request-response cycle.
So service workers intercept the request and route it to the MSW library, which acts as a server and sends the response.
This way, we mock the API, and your app doesn't know what happens here!

Setup:
Create a directory called 'mocks' inside src.
Create a file called 'handlers.js' inside the 'mocks' directory.
We are using REST API.
We will create a mocking server by using MSW.
Create a file called 'server.js' inside the 'mocks' directory.

We will have to create handlers, but before that, let us create an API fetching component.

When using MSW, you can define "handlers" for each HTTP request your application makes. These handlers are functions that take the incoming request as an argument and return a mocked response.
Handlers are arrays.
Why are they arrays?
Handlers in Mock Service Workers are defined as an array of functions because it allows you to define multiple handlers for the same endpoint.
MSW will match the incoming request to the first matching handler in the array.
For example,
you may have one handler that returns a successful response and another that simulates an error response.
By defining both handlers in the array, you can easily switch between them during testing or development.
Each element in an array is a function that defines REST methods like 'res.get', 'rest.post' , etc.
It's more like express node js because we are creating the server.
Let's use
res.get ('your api url' , (req,res,ctx) => { do something on req and return res using ctx}

Once you have set up the mock server, you can start it by calling its listen method before your tests run and then stop it by calling its close method after your tests have been completed.
By starting the mock server before your tests run and stopping it after they complete, you can ensure that all HTTP requests made by your application during testing are intercepted and handled by the mock server, allowing you to test your application's behavior in different scenarios without making actual network requests.

Note: async - await and findAllbyRole for asynchronous operations
Error handling in request:
For handling errors, we cannot change the handler.js because it will be applied to all tests.
So we will create an error response within the test itself.
For that error tests, we can change the server response using: server.use method

I hope you get the basic idea about testing different scenarios.