Storybook 快照测试为啥没捕捉到 CSS 样式变化?

程序员东旭 阅读 4

我在用 Storybook 做组件快照测试,但发现即使改了组件的样式,快照也没更新。比如我调整了一个按钮的 padding 和背景色,Jest 的 snapshot 测试居然通过了,根本没报错。是不是快照测试默认不包含 CSS?

我试过用 @storybook/testing-react 里的 composeStories,也确认 story 能正常渲染,但样式改动就是没被记录。下面是我改的那段 CSS:

.my-button {
  padding: 12px 24px;
  background-color: #007bff;
  border: none;
  border-radius: 4px;
  color: white;
}

难道快照只保存了 HTML 结构,没管样式?那怎么才能让快照对样式变更敏感呢?

我来解答 赞 3 收藏
二维码
手机扫码查看
1 条解答
❤忠娟
❤忠娟 Lv1
根本原因是 Jest 的快照测试默认只捕获组件的 HTML 结构,而不包括样式信息。也就是说,即使你改变了组件的样式,只要 HTML 结构不变,快照测试就会通过。

要解决这个问题,可以使用 jest-styled-components 或者 jest-emotion 这样的库来帮助 Jest 捕获和比较样式。不过,对于普通的 CSS 文件,我们可能需要一些额外的配置。

一种方法是使用 jest-image-snapshot 来捕获组件的视觉快照。这种方法不仅能够捕捉到 HTML 结构的变化,还能捕捉到样式的变化。

以下是具体步骤:

1. 安装必要的依赖包:

npm install --save-dev jest-image-snapshot puppeteer @testing-library/react


2. 配置 Jest 使用 puppeteerjest-image-snapshot。可以在你的测试文件中添加如下代码:

import React from 'react';
import { render } from '@testing-library/react';
import { composeStories } from '@storybook/testing-react';
import * as stories from './Button.stories'; // 替换为你的故事文件路径

const { Default } = composeStories(stories);

describe('Button', () => {
it('matches the snapshot', async () => {
const { container } = render(<Default />);
const image = await captureComponent(container);
expect(image).toMatchImageSnapshot();
});
});

// 使用 puppeteer 捕获组件的屏幕截图
async function captureComponent(component) {
const puppeteer = require('puppeteer');
const browser = await puppeteer.launch();
const page = await browser.newPage();

// 将组件渲染到一个临时的 HTML 文件中
const fs = require('fs');
const path = require('path');
const htmlPath = path.resolve(__dirname, 'temp.html');
const htmlContent =
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="path/to/your/styles.css" /> <!-- 替换为你的 CSS 文件路径 -->
</head>
<body>
${component.innerHTML}
</body>
</html>
;
fs.writeFileSync(htmlPath, htmlContent);

await page.goto(file://${htmlPath});
const image = await page.screenshot({ fullPage: false });

await browser.close();
fs.unlinkSync(htmlPath); // 删除临时文件

return image;
}


在这个例子中,我们首先使用 @testing-library/react 渲染组件,然后使用 puppeteer 将组件的 HTML 结构和样式捕获为图像,并使用 jest-image-snapshot 来比较这个图像是否与之前的快照匹配。

注意,这种方法会稍微增加测试的时间,因为它需要启动浏览器并截屏。但是,这确保了你的样式变化会被捕获到。

希望这些步骤能帮助你解决快照测试无法捕捉 CSS 样式变化的问题。
点赞
2026-03-24 23:01