-
-
Notifications
You must be signed in to change notification settings - Fork 9.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Question]: How to mount NextRouter in tests when using framework @storybook/nextjs #22538
Comments
Thank you for opening up this issue. Indeed, you could import and use the custom decorator, which is automatically applied to each Next.js story also in your tests: import { composeStories } from '@storybook/react'
import { decorators } from '@storybook/nextjs/preview.js'
import { render, screen } from '@testing-library/react'
import * as stories from './MyComp.stories'
const { Default } = composeStories(stories, { decorators })
test('My test', () => {
render(<Default />)
screen.getByText(/Path : \/toto/i)
}) You will encounter a Typescript error, though, that the type declaration for the module Would you mind opening up a PR to add the necessary instructions in the Readme of the |
Hello, I've been trying to get this to work with vite, and no joy: FAIL src/questions/question-editor/question-editor.test.tsx [ src/questions/question-editor/question-editor.test.tsx ]
Error: Cannot find module '/Users/pedro/dev/chair-flight-monorepo/node_modules/.pnpm/@[email protected]_@[email protected]_@[email protected]_@[email protected]_esbuild_y7peqbgta5yxnw4uvcg2d6o5eu/node_modules/next/config' imported from /Users/pedro/dev/chair-flight-monorepo/node_modules/.pnpm/@storybook+nextjs@7.2.1_@swc+core@1.3.74_@types+react-dom@18.2.7_@types+react@18.2.18_esbuild_y7peqbgta5yxnw4uvcg2d6o5eu/node_modules/@storybook/nextjs/dist/preview.mjs
Did you mean to import next@13.4.12_@babel+core@7.22.9_react-dom@18.2.0_react@18.2.0/node_modules/next/config.js? the problematic
import { composeStories } from '@storybook/react';
import * as stories from './question-editor.stories';
import { decorators } from '@storybook/nextjs/preview.js'
import { render, screen } from '@testing-library/react';
import { default as userEvent } from '@testing-library/user-event';
const { BasePage } = composeStories(stories, { decorators });
describe('QuestionEditor', () => {
it('is possible to create a new variant', async () => {
render(<BasePage />);
const numberOfCards = screen.getAllByTestId('variant-card').length;
const addButton = screen.getByRole('button', { name: /new variant/i });
await userEvent.click(addButton,);
const newNumberOfCards = screen.getAllByTestId('variant-card').length;
expect(newNumberOfCards).toBe(numberOfCards + 1);
});
}); I've kind of ran out of ideas when trying to configure vite. Stuff like inline deps, don't work.... any ideas? |
When I apply the decorator manually as described, the tests return:
Is there additional config required? Thanks! PS. node_modules/next/config.js is definitely there. |
Hello everyone, I recently faced a similar issue and fixed it by leveraging the In my particular case, I added this provider as a wrapper to my component, for a particular Story, but I guess it could be included as a global decorator, at the // simplified, for the sake of brevity; not actual code
import React from 'react';
import { Meta } from '@storybook/react';
import { MemoryRouterProvider } from 'next-router-mock/MemoryRouterProvider/next-13';
export const WithBackButton = {
render: (): JSX.Element => (
<MemoryRouterProvider>
<MyComponent url={'/home'} />
</MemoryRouterProvider>
),
}; Let me know if you need any further details about my context and the solution. Cheers! |
I wish we didn't need a separate package to make this work. After investigation, problem comes from this PR #24834 |
The problem is that decorators in dist/preview are not exposed. moduleNameMapper: {
...
'@storybook/nextjs/dist/preview': '<rootDir>/node_modules/@storybook/nextjs/dist/preview',
}, In my jest setup : // @ts-expect-error This import is resolved through jest module mapper
import { decorators as nextFrameworkDecorators } from '@storybook/nextjs/dist/preview'
import { setProjectAnnotations } from '@storybook/react'
import globalStorybookConfig, { decorators as globalStorybookConfigDecorators } from '../.storybook/preview'
const newConfig = {
...globalStorybookConfig,
// Add decorator from @storybook/nextjs framework
// https://github.com/storybookjs/storybook/issues/22538
decorators: [...globalStorybookConfigDecorators, ...nextFrameworkDecorators],
}
setProjectAnnotations(newConfig) |
Hey everyone! Thanks a lot for elaborating the issues. For the time being, please use the workarounds suggested. In Storybook 8.1, we will be releasing portable-stories (composeStories) API in the @storybook/nextjs package, which will contain all the necessary internals to get things to work correctly. Storybook 8.1 will be released shortly after Storybook 8.0 is released (which is currently in RC stage). Thank you so much for your patience!! 🙏 |
I can't to make this work with Storybook 8.1+. What I understand is that importing the nextjs decorators manually from @storybook/nextjs is no longer necessary when importing composeStories from @storybook/nextjs, and indeed when I do that I don't have the "NextRouter was not mounted" error, but I have another one : Error: Uncaught [SB_FRAMEWORK_NEXTJS_0002 (NextjsRouterMocksNotAvailable): Tried to access router mocks from "next/router" but they were not created yet. You might be running code in an unsupported environment.] Should I open a new issue ? |
I'm hitting this as well with FWIW even in the case where the tests do pass in the edit: I was able to get around this for now by composing individually stories separately instead of leveraging the ones from it("should render as readonly", async () => {
const ComposedStory = composeStory(
{
...stories.PackageIsSelected,
args: {
...composedStories.PackageIsSelected.args,
deal: { ...mockDeal, writable: false },
},
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
expect(...)
},
},
stories.default
);
await ComposedStory.play();
}); |
cc @kasperpeulen, @yannbf |
Using Storybook 8.2.9, Jest 29.7.0 I was able to get rid of the error:
Building on the ideas by @Mattgic, I added const nextJest = require('next/jest');
/** @type {import('jest').Config} */
const createJestConfig = nextJest({
// Provide the path to your Next.js app to load next.config.js and .env files in your test environment
dir: './',
});
// Add any custom config to be passed to Jest
const config = {
coverageProvider: 'v8',
testEnvironment: 'jsdom',
// Add more setup options before each test is run
setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
moduleNameMapper: {
// Make preview and export-mocks available
'@storybook/nextjs/dist/preview': '<rootDir>/node_modules/@storybook/nextjs/dist/preview',
'@storybook/nextjs/dist/export-mocks/router': '<rootDir>/node_modules/@storybook/nextjs/dist/export-mocks/router',
},
}
// createJestConfig is exported this way to ensure that next/jest can load the Next.js config which is async
module.exports = createJestConfig(config); By importing and calling // stories.test.js
import '@testing-library/jest-dom';
import { createRouter, getRouter } from '@storybook/nextjs/dist/export-mocks/router';
import { RouterContext } from 'next/dist/shared/lib/router-context.shared-runtime';
import { setProjectAnnotations } from '@storybook/nextjs';
import { decorators as nextFrameworkDecorators } from '@storybook/nextjs/dist/preview';
import globalStorybookConfig, { decorators as globalStorybookConfigDecorators } from '../.storybook/preview';
const newConfig = {
...globalStorybookConfig,
// Add decorator from @storybook/nextjs framework
// https://github.com/storybookjs/storybook/issues/22538
decorators: [...globalStorybookConfigDecorators, ...nextFrameworkDecorators],
}
setProjectAnnotations(newConfig)
// Create a mock router using createRouter from @storybook/nextjs/dist/export-mocks/router
createRouter({ globals: { locale: 'en' }, routeParams: {}});
// (Optional) Get the mock router using getRouter from @storybook/nextjs/dist/export-mocks/router
const mockRouter = getRouter(); // Get the mock router |
I encountered the same issue with storybook 8.3.2 and @storybook/nextjs 8.3.2. I have the app router set up in The following errors occurred:
To resolve this, simply add import { createRouter } from '@storybook/nextjs/router.mock';
import { createNavigation } from '@storybook/nextjs/navigation.mock';
createRouter();
createNavigation(); |
I have followed the workaround. But it's simply throw the error
while calling the FYI: I'm using the latest storybook version 8.3.3 for all packages. |
Storybook 8.3.5, Jest 29.5.0 For app router environment, I was able to get away with this:
No moduleNameMapper needed this way. Component example:
Story example:
Test example:
|
Describe the bug
When using
@storybook/nextjs
framework andcomposeStories
from@storybook/react
to import my stories in my tests, I have this error saying "NextRouter was not mounted" on components that need Next router.I made a reproduction repo here : https://github.com/Mattgic/repro-storybook-nextjs-tests
Before updating to Storybook 7, I was using storybook-addon-next-router. Everything worked fine, from my stories to my tests. The addon configuration included adding a custom global provider & decorator in my preview.ts. As the whole preview configuration is used in the
setProjectAnnotations
call (formerly setGlobalConfig) for my jest tests, my stories in my tests include this decorator and everything works fine.@storybook/nextjs documentation doesn't talk about importing stories in tests. Maybe there is a custom decorator I'm missing.
What I don't get about the new framework option is that it seems to only be a build config. But if this next router "decorator" is only added on Storybook build, I can't have it in my tests too.
To Reproduce
https://github.com/Mattgic/repro-storybook-nextjs-tests
System
No response
Additional context
No response
The text was updated successfully, but these errors were encountered: