You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Storyshots不遵守视口宽度配置:指定自定义视口仍以1024px渲染组件

问题原因说明

这不是已知Bug,属于配置遗漏问题。Storybook官方的viewport插件的参数默认仅作用于Storybook的可视化预览界面,不会自动同步到Storyshots的Jest/jsdom测试环境,默认jsdom的视口宽度就是1024px,所以会出现你遇到的情况。

修复方案

你需要改造Storyshots的测试逻辑,在渲染每个story前主动读取viewport配置,修改jsdom的视口参数,示例配置如下:

import { initStoryshots, multiSnapshotWithOptions } from '@storybook/addon-storyshots';
import { Stories2SnapsConverter } from '@storybook/addon-storyshots';
// 导入你定义的所有视口配置
import { allViewports } from './your-viewport-config-path';

const customSnapshotTest = async ({ story, context }) => {
  // 读取当前story的viewport参数
  const viewportParams = story.parameters?.viewport;
  if (viewportParams) {
    const targetViewport = viewportParams.defaultViewport;
    const viewportConfig = viewportParams.viewports[targetViewport] || allViewports[targetViewport];
    if (viewportConfig?.styles) {
      // 提取宽高数值,去掉px单位
      const width = parseInt(viewportConfig.styles.width, 10);
      const height = parseInt(viewportConfig.styles.height, 10);
      // 修改jsdom视口
      Object.defineProperty(window, 'innerWidth', { writable: true, configurable: true, value: width });
      Object.defineProperty(window, 'innerHeight', { writable: true, configurable: true, value: height });
      // 触发resize事件,保证监听视口变化的组件能正常更新
      window.dispatchEvent(new Event('resize'));
    }
  }
  // 执行原有快照逻辑
  const testFn = multiSnapshotWithOptions({
    createNodeMock: (element) => element,
  });
  return testFn({ story, context });
};

initStoryshots({
  test: customSnapshotTest,
  stories2snapsConverter: new Stories2SnapsConverter({
    snapshotsDirName: './__snapshots__',
  }),
});
额外注意事项
  • 如果你的组件使用window.matchMedia做响应式判断,还需要额外模拟matchMedia的返回结果,和视口尺寸保持一致
  • 若快照中还是读取不到正确的组件宽度,可以调整createNodeMock逻辑,给DOM节点模拟正确的clientWidth/offsetWidth属性

内容的提问来源于stack exchange,提问作者GaelF

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 16:30:03