msal-react-tester
Version:
A npm package to simplify testing react application using msal-react
188 lines (135 loc) • 6.56 kB
Markdown
//www.npmjs.com/package/msal-react-tester) is a NPM package to allows you creating **unit tests** for any of your components that need to be authenticated (or not) using the `msal-react` package and [Azure AD](https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-overview).
The **MSAL React Tester** package is able to run by default with different javascript test runners like:
- [vitest](https://vitest.dev/) if you are creating a React application using [vite](https://vitejs.dev/).
- [jest](https://jestjs.io/) if you are creating a React application using [Create React Application](https://create-react-app.dev/).
The **MSAL React Tester** package allows you to test your components in any of these scenario:
- Testing a react component when a user "**is not**" authenticated.
- Testing a react component when a user "**is**" authenticated.
- Testing a react component when a user "**tries**" to log in.
- Testing a react component when a user "**tries**" to log out.
- Testing a react component when a user authentication request has "**failed**".
* You are building a react application using [Create React Application](https://create-react-app.dev/) or [vite](https://vitejs.dev/).
* You are using `@azure/msal-react` to authenticate your users on [Azure AD](https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-overview).
* You are using the built in `@testing-library/react` package to create and run your tests (you are basically using the built in `"test": "react-scripts test"` script to execute your tests).
* You want to create unit tests without having to depends on a connection to [Azure AD](https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-overview).
* You want to run your tests in your **CI/CD**.
## Installation
The **MSAL React Tester** package is available on [NPM](https://www.npmjs.com/).
``` bash
npm install --save-dev msal-react-tester
```
### vitest
If you are using the [vitest](https://vitest.dev/) test runner, you need to add this to your config
``` ts
import { MsalReactTesterPlugin } from 'msal-react-tester'
import { vi, expect } from 'vitest'
MsalReactTesterPlugin.init({
spyOn: vi.spyOn,
expect: expect,
resetAllMocks: vi.resetAllMocks
})
```
If you are using [jest](https://jestjs.io/) this step is not necessary.
Creates a `[component].test.tsx` and import the msal-react-tester package:
``` ts
import { MsalReactTester } from 'msal-react-tester';
```
- Create a new instance of `MsalReactTester` before each test.
- Depending on your setup, you can create your instance to mock a **Redirect authentication** or a **Popup authentication**.
- Call the `spyMsal()` method to mock all the MSAL React required methods & events.
- Don not forget to call `resetSpyMsal` after each test.
``` ts
let msalTester: MsalReactTester;
beforeEach(() => {
// new instance of msal tester for each test:
msalTester = new MsalReactTester();
// or new MsalReactTester("Redirect") / new MsalReactTester("Popup")
// Ask msal-react-tester to handle and mock all msal-react processes:
msalTester.spyMsal();
});
afterEach(() => {
// reset msal-react-tester
msalTester.resetSpyMsal();
});
```
In each of your test, you can now:
- Mock an unauthenticated user, calling `await msalTester.isNotLogged()`.
- Mock an authenticated user, calling `await msalTester.isLogged()`.
- Creates a `<MsalProvider />` using the `msalTester.client` as the `IPublicClientApplication` instance.
- Call `msalTester.waitForRedirect()` to let **MSAL React Tester** handling **MSAL React** processes
- Then makes any tests or assertions.
Here is an example where we are testing a `<HomePage />` component during a first visit by an authenticated user:
``` ts
test('Home page render correctly when user is not logged', async () => {
// Mock a guest user, not yet authenticated:
await msalTester.isNotLogged();
// Render the <HomePage /> component using a <MsalProvider />
// with the mock IPublicClientApplication instance:
render(
<MsalProvider instance={msalTester.client}>
<MemoryRouter>
<Layout>
<HomePage />
</Layout>
</MemoryRouter>
</MsalProvider>,
);
// Wait for msal-react-tester to handle events from msal-react:
await msalTester.waitForRedirect();
// Test your <HomePage /> component:
expect(screen.getByText(/Please sign-in/)).toBeInTheDocument();
});
```
On the other side, you can test the same component assuming your user is "_already logged_", using `await msalTester.isLogged()`.
If you want to test a component during the authentication process, you can use `await msalTester.waitForLogin()`:
``` ts
test('Home page render correctly when user logs in', async () => {
// Mock a guest user, not yet authenticated:
await msalTester.isNotLogged();
// Render the <HomePage /> component using a <MsalProvider />
// with the mock IPublicClientApplication instance:
render(
<MsalProvider instance={msalTester.client}>
<MemoryRouter>
<Layout>
<HomePage />
</Layout>
</MemoryRouter>
</MsalProvider>,
);
// Wait for msal-react-tester to handle events from msal-react:
await msalTester.waitForRedirect();
// Getting the log in button.
// Mock a user click to launch the log in process:
const signin = screen.getByRole('button', { name: 'Sign In' });
userEvent.click(signin);
// Wait for msal-react-tester to handle the login process from msal-react:
await msalTester.waitForLogin();
// From here, your user is supposed to be logged in the component:
expect(screen.getByRole('button',
{ name: msalTester.activeAccount.name })).toBeInTheDocument();
});
```
On the other side, if you want to test component during a log out process, use `msalTester.waitForLogout()`
You will find a full example in the `../example` folder.
Take a look on the pages tests:
```
root
├── example
├──── src
├────── pages
├──────── HomePage.test.tsx
├──────── SearchPage.test.tsx
```
Licensed under the MIT License.
Feel free to contact me through twitter : [@sebpertus](https://twitter.com/sebpertus)
The [MSAL React Tester](https: