Skip to content
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

[Bug] Tests always run in the default viewport #85

Closed
schneefux opened this issue Apr 4, 2022 · 9 comments
Closed

[Bug] Tests always run in the default viewport #85

schneefux opened this issue Apr 4, 2022 · 9 comments
Labels
feature request New feature or request

Comments

@schneefux
Copy link

Describe the bug

The test runner runs tests full screen inside the default playwright Chrome viewport. It does not resize the viewport according to the viewport parameter of the story.

Steps to reproduce the behavior

I have a component where a dropdown is hidden on large screens using a media query. I configured the story to use a mobile2 viewport by default and wrote a play function to test the visibility of the element:

export const Mobile = Template.bind({})
Mobile.parameters = {
  viewport: {
    defaultViewport: 'mobile2',
  },
}
Mobile.play = async ({ canvasElement }) => {
  const canvas = within(canvasElement)
  const toggleButton = await canvas.findByTestId('dropdownToggle')
  await waitFor(() => expect(toggleButton).toBeVisible())
}

When I run storybook locally and use the interactions addon, the test runs fine, but when I run the test runner, it fails.

I debugged the test runner using this custom test-runner-jest.config.js, --maxWorkers 1 and by adding sleep timeouts after every line. I can see that the playwright Chrome window has the wrong size and that it loads the story iframe in fullscreen.

const { getJestConfig } = require('@storybook/test-runner');

module.exports = {
  ...getJestConfig(),
  testEnvironmentOptions: {
    'jest-playwright': {
      launchOptions: {
        headless: false,
      }
    },
  },
}

Environment

  • Storybook 6.4.20
  • @storybook/test-runner 0.0.4
  • @storybook/testing-library 0.0.9

Additional context

As a workaround, I wrote a prerender hook in .storybook/test-runner.js that resizes the playwright page if the test has Mobile in its name. A solution that does not rely on magic strings would be better though.

module.exports = {
  preRender(page, story) {
    if (story.name.includes('Mobile')) {
      page.setViewportSize({ width: 896, height: 414 })
    }
  },
}
@schneefux schneefux added the bug Something isn't working label Apr 4, 2022
@yannbf
Copy link
Member

yannbf commented Apr 4, 2022

Thanks for using this library and opening this issue @schneefux! There's currently a limitation that won't allow you to get info from the viewports addon, hopefully we can add support for that soon.

@shilman WDYT of adding parameters to the context? It will make stories-json mode feel more limited but it is what it is I guess

@yannbf yannbf added feature request New feature or request and removed bug Something isn't working labels Apr 4, 2022
@IanVS
Copy link
Member

IanVS commented Apr 6, 2022

It will make stories-json mode feel more limited.

Is that because parameters are not available in stories-json mode? This could be another good use for tags in storybook, perhaps.

@VickyKoblinski
Copy link

I just want to share that this is possible now with the getStoryContext/page.evaluate.

I'm using it to get storyContext.parameters.viewport.defaultViewport and then calling page.setViewportSize(devices[storyContext.parameters.viewport.defaultViewport].viewport) where devices is a shared list between the custom viewports I've set up in storybook (and I'm leveraging playwright's devices because why not :) const { devices } = require("playwright");)

@yannbf
Copy link
Member

yannbf commented Aug 14, 2022

Thanks @VickyKoblinski! Your project must be super cool, given all the stuff you've been doing with the test runner!

@yannbf
Copy link
Member

yannbf commented Aug 14, 2022

TODO: add a recipe for that ☝️

@ibrahimgabsi
Copy link

ibrahimgabsi commented Jan 27, 2023

We got inspired by @VickyKoblinski's answer with little changes, our stories are configured with viewports imported or customized with @storybook/addon-viewport. So here's our little magic 🍡 :
`

const { getStoryContext } = require('@storybook/test-runner'); 
module.exports = {
    async preRender(page, story) {
      const context = await getStoryContext(page, story);
      const viewPortParams = context.parameters?.viewport;
      const defaultViewport = viewPortParams?.defaultViewport;
      const viewport =
        defaultViewport && viewPortParams.viewports[defaultViewport].styles;

      const parsedViewportSizes =
        viewport &&
        Object.entries(viewport).reduce(
          (acc, [screen, size]) => ({
            ...acc,
            [screen]: parseInt(size),
          }),
          {},
        );

      if (parsedViewportSizes) page.setViewportSize(parsedViewportSizes);
  },
};`

@dimkatet
Copy link

@ibrahimgabsi I want to note that when the viewPort is resized, it will not return to its original state for the following stories. So we have to call something like setViewportSize(globalDefaultSize) if no custom window is specified.

@vlad-iakovlev
Copy link

I slightly improved solution of @ibrahimgabsi to use built-in viewport sizes or reset to default on pages without viewport parameter.

Create .storybook/test-runner.js:

const { getStoryContext } = require('@storybook/test-runner');
const { MINIMAL_VIEWPORTS } = require('@storybook/addon-viewport');

const DEFAULT_VP_SIZE = { width: 1280, height: 720 };

module.exports = {
	async preRender(page, story) {
		const context = await getStoryContext(page, story);
		const vpName = context.parameters?.viewport?.defaultViewport;
		const vpParams = MINIMAL_VIEWPORTS[vpName];

		if (vpParams) {
			const vpSize = Object.entries(vpParams.styles).reduce(
				(acc, [screen, size]) => ({
					...acc,
					[screen]: parseInt(size),
				}),
				{}
			);

			page.setViewportSize(vpSize);
		} else {
			page.setViewportSize(DEFAULT_VP_SIZE);
		}
	},
};

@yannbf
Copy link
Member

yannbf commented Oct 25, 2023

Hey peeps! I will close this issue as the solution is now available and its recipe has been documented in the README here. Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature request New feature or request
Projects
None yet
Development

No branches or pull requests

7 participants