@tomfreudenberg/next-auth-mock
Version:
NextAuth.js mockup provider for jest, storybook and others.
414 lines (294 loc) • 8.86 kB
Markdown
<h3 align="center">NextAuth.js Mockup</h3>
<p align="center">
<strong>Some helpful tool library to write tests and stories for your <a href="https://next-auth.js.org/">NextAuth.js</a> powered <a href="https://nextjs.org/">NEXT.js</a> application.</strong>
</p>
<p align="center">
-- use it with nodejs and jest, storybook, cypress, others --
</p>
<br>
<br>
Install this library by adding it to your devDependencies:
```bash
pnpm add --save-dev @tomfreudenberg/next-auth-mock
```
<br>
<br>
Update `.storybook/main.js` and append to your list of addons:
```js
module.exports = {
addons: ['@tomfreudenberg/next-auth-mock/storybook']
}
```
<br>
After restarting your storybook, an additional icon will appear in the toolbar:
<img width="191" alt="image" src="https://user-images.githubusercontent.com/410087/193901653-12114ea3-9a4c-4d93-ac93-46576a2409e6.png">
That allows you to select the session state.
<br>
```jsx
// ./stories/pages/denied.stories.jsx
import DeniedPage from '@/pages/auth/denied';
export default {
title: 'Pages/Auth',
component: DeniedPage
};
export const DeniedPageStory = (args) => <DeniedPage />;
DeniedPageStory.parameters = {};
```
<br>
You may now control and test your component state of `useSession()` by the toolbar items:

<br>
To make sure that your component may be tested with a fixed auth state regardless the toolbar selection, you may overwrite the session properties by using parameters in your stories:
```jsx
// /stories/pages/signin.stories.jsx
import SigninPage from '@/pages/auth/signin';
export default {
title: 'Pages/Auth',
component: SigninPage
};
export const SigninPageStory = (props) => <SigninPage />;
SigninPageStory.parameters = {
nextAuthMock: {
session: 'unknown'
}
};
```
The above will load the session set defined by id `unknown`. You may also define a full session object like:
```js
SigninPageStory.parameters = {
nextAuthMock: {
session: {
data: {
id: 999,
login: 'user',
role: 'user',
roles: ['user'],
username: 'User',
email: 'user@local'
},
status: 'unauthenticated'
}
}
};
```
<br>
If you need to change your stories code while using session values, you may access those by the `useSession` hook.
```jsx
import { useSession } from 'next-auth/react';
export const MyStory = (props) => {
// get access to current session data
const session = useSession();
...
```
<br>
This component brings a default set of auth states: `unknown`, `loading`, `admin`, `adminAuthed`, `user`, `userAuthed`.
<details>
<summary>Show default preview mockAuthStates</summary>
```js
/**
*
* default items for toolbar menu to select different auth-states while mocking
*
*/
export const mockAuthStates = {
unknown: {
title: 'session unknown',
session: null
},
loading: {
title: 'session loading',
session: {
data: null,
status: 'loading'
}
},
admin: {
title: 'admin not authenticated',
session: {
data: {
id: 1,
login: 'admin',
role: 'admin',
roles: ['admin', 'user'],
username: 'Administrator',
email: 'admin@local'
},
status: 'unauthenticated'
}
},
adminAuthed: {
title: 'admin authenticated',
session: {
data: {
id: 1,
login: 'admin',
role: 'admin',
roles: ['admin', 'user'],
username: 'Administrator',
email: 'admin@local'
},
status: 'authenticated'
}
},
user: {
title: 'user not authenticated',
session: {
data: {
id: 999,
login: 'user',
role: 'user',
roles: ['user'],
username: 'User',
email: 'user@local'
},
status: 'unauthenticated'
}
},
userAuthed: {
title: 'user authenticated',
session: {
data: {
id: 999,
login: 'user',
role: 'user',
roles: ['user'],
username: 'User',
email: 'user@local'
},
status: 'authenticated'
}
}
};
```
</details>
<br>
This set may be changed completely or in partials for your own needs. Therefore you may create a file in your local folder named `.storybook/previewMockAuthStates.js` and define an alias for webpack.
Update `.storybook/main.js`:
```js
module.exports = {
addons: ['@tomfreudenberg/next-auth-mock/storybook'],
webpackFinal: async (config) => {
config.resolve.alias['@tomfreudenberg/next-auth-mock/storybook/preview-mock-auth-states'] = path.resolve(__dirname, 'previewMockAuthStates.js');
}
};
```
Webpack will now load your file `.storybook/previewMockAuthStates.js` for the previewMockAuthStates set:
<br>
```js
const defaultMockAuthStates = require('@tomfreudenberg/next-auth-mock').mockAuthStates;
module.exports = defaultMockAuthStates;
```
<br>
```js
const defaultMockAuthStates = require('@tomfreudenberg/next-auth-mock').mockAuthStates;
module.exports = {
...defaultMockAuthStates,
admin: {
title: 'My Admin unauthenticated',
session: {
data: {
id: 777,
field: 'Additional session field'
}
}
}
}
```
<br>
```js
module.exports = {
state0: {
title: 'State zero',
session: null
},
state1: {
title: 'A State',
session: {
data: {
id: 1,
user: 'What you like'
}
}
}
}
```
<br>
The toolbar entry can also be changed completely. For that you need to implement manually the decorator in `preview.js` and just set the options to `mockAuthPreviewToolbarItem()` as you like. Attention: Do not add the component to the addons in this case.
Update `.storybook/preview.js`:
```js
import { mockAuthPreviewToolbarItem, withMockAuth } from '@tomfreudenberg/next-auth-mock/storybook';
import { previewMockAuthStates } from '@tomfreudenberg/next-auth-mock/storybook/preview-mock-auth-states';
export const globalTypes = {
...mockAuthPreviewToolbarItem({
description: 'Auswahl Anmeldestatus',
defaultValue = null,
icon = 'user',
items = previewMockAuthStates
})
};
export const decorators = [withMockAuth];
```
<br>
```jsx
// ./tests/pages/signout.stories.jsx
import { render, screen } from '@testing-library/react'
import { withMockAuth } from '@tomfreudenberg/next-auth-mock/jest';
import SignoutPage from '@/pages/auth/signout';
describe('Pages', () => {
describe('Signout', () => {
it('should render want to sign out', () => {
render(withMockAuth(<SignoutPage />, 'userAuthed'));
expect(screen.getByText('Do you want to sign out?'));
});
it('should render not signed in', () => {
render(withMockAuth(<SignoutPage />, 'unknown'));
expect(screen.getByText('You are not signed in!'));
});
});
});
```
You may enter the name of an `mockAuthStates` entry as argument for `withMockAuth` or put in a session object.
```jsx
import { mockAuthStates } from '@tomfreudenberg/next-auth-mock';
render(withMockAuth(<SignoutPage />, mockAuthStates.userAuthed.session));
// is equal to
render(withMockAuth(<SignoutPage />, 'userAuthed'));
```
Valid states are: `unknown`, `loading`, `admin`, `adminAuthed`, `user`, `userAuthed`
<br>
If you like to contribute to next-auth-mock package or need to use it from source, you have to install the devDependencies and build the dist package.
Just go for:
```bash
git clone git@github.com:TomFreudenberg/next-auth-mock.git
cd next-auth-mock
pnpm install
pnpm build
```
Your ideas and PRs are welcome.
<br>
You may find, use and download the npm package on [npmjs.com](https://npmjs.com/package/@tomfreudenberg/next-auth-mock).
[](https://npmjs.com/package/@tomfreudenberg/next-auth-mock)
<br>
**[Project homepage](https://github.com/TomFreudenberg/next-auth-mock)** - you will find a README at [Github](https://github.com/TomFreudenberg/next-auth-mock)
<br>
Author: [Tom Freudenberg](https://about.me/tom.freudenberg)
Copyright (c) 2022 [Tom Freudenberg](https://github.com/TomFreudenberg/), released under the MIT license