I have a NextJS application with an app router that uses NextAuth.js that also includes Storybook.
Within the project, we have a HOC that wraps specific components with the authentication context (cutting out some of the Typescript markup to make it more succinct):
// context/AuthProvider.tsx
import { SessionProvider } from 'next-auth/react';
// ...
export default function AuthProvider({children}) {
return <SessionProvider>{children}</SessionProvider>
}
// hoc/withAuthProvider.tsx
export const withAuthProvider = (WrappedComponent) => {
const ComponentWithSP = (props) => {
<AuthProvider>
<WrappedComponent {...props} />
</AuthProvider>
};
return ComponentWithSP;
}
When the components are defined, they have:
export default withAuthProvider(MyClientComponent);
I want to write a Storybook story for MyClientComponent
but cannot figure out how to mock the session or inject a mocked session.
My basic story looks like this:
import type { Meta, StoryObj } from '@storybook/react';
import MyClientComponent from './MyClientComponent';
const meta: Meta<typeof MyClientComponent> = {
title: 'MyClientComponent',
component: MyClientComponent,
};
export default meta;
export const MyClientComponentStory: StoryObj<typeof MyClientComponent> = {
name: 'MyClientComponent',
};
Grabbing the session I didn't do anything special:
const { data: session, status } = useSession({
required: true,
onUnauthenticated() {
redirect('/api/auth/signin');
},
});
I found these:
Versions in use:
Try the following - just some ideas below...
Edit .storybook/preview.js
to include a custom decorator that wraps your components with the SessionProvider
(from NextAuth.js
).
Then try to create a mock session object that reflects the state you want to simulate.
Use the mocked session in the SessionProvider.
Quick example (not working - but as an idea):
// .storybook/preview.js
import { SessionProvider } from 'next-auth/react';
const mockSession = {
expires: '2023-01-01T00:00:00Z',
user: {
name: 'Storybook User',
email: 'storybook@mySite.com',
},
};
export const decorators = [
(Story) => (
<SessionProvider session={mockSession}>
<Story />
</SessionProvider>
),
];
Now, when you define your Storybook stories:
// MyComponent.stories.js
import MyClientComponent from '../components/MyClientComponent';
export default {
title: 'MyClientComponent',
component: MyClientComponent,
};
export const Primary = () => <MyClientComponent />;
Give something like this a try and let me know if this helps you out!