BackstopJS - 为所有场景设置公共选择器

BackstopJS - Set common selector for all scenarios

我正在使用 BackstopJS 运行 对一些 React 组件进行视觉回归测试。我的所有组件都显示在 "common" 包装器内的各个 Storybook 页面上。

例如,Storybook 中的每个故事都设置为显示以下内容:

<div key="my_unique_key" id="component_preview">
  <MyReactComponentHere />
</div>

由于我的所有组件都显示在 ID 为 component_preview 的公共容器内的单独页面上,因此我想在 BackstopJS 中为 all[=34] 设置一个选择器=] 测试套件,因为这是每个测试的屏幕截图的重点(即,这是因为我避免捕获每个页面上随组件显示的任何降价或道具表)。

我知道我可以在每个场景中单独设置它,如下所示:

scenarios: [
  {
    ...
    selectors: [
      'div[id="component_preview"]'
    ],
    ...
  }
],

但考虑到我可能有大量场景(这是一个不断发展的项目,所以我不知道将来我想单独捕获多少组件),我想可以将其设置为所有场景的一般规则,而不必为每个场景单独设置。

我尝试在 scenarios 配置之外设置一个 selectors 数组,但没有任何效果。

是否可以为所有场景设置一个像这样的通用选择器,而不必在每个场景上单独设置它?

如果我必须在每个场景中单独设置它没什么大不了的(只是意味着更多的工作/相同配置的重复)但我想尽可能避免这样做。

好的,所以我一直在做一些这方面的工作,并提出了这个解决方案,它可以满足我的需求,无需设置要在每个场景中捕获的通用选择器。

最初的目标是单独捕获我的 React 组件,显示在 Storybook 上(即没有 markdown 或 prop 表妨碍)。

仅供大家参考,这些是我正在使用的相关依赖项和版本(从我的项目package.json文件中复制粘贴):

"@storybook/addon-actions": "^3.4.8",
"@storybook/addon-info": "^3.4.8",
"@storybook/addon-links": "^3.4.8",
"@storybook/addon-options": "^3.4.8",
"@storybook/addons": "^3.4.8",
"@storybook/react": "^3.4.8",
"backstopjs": "^3.2.19",
"prop-types": "^15.6.2",
"react": "^16.4.1",
"react-dom": "^16.4.1"

进一步说明,我将 puppeteerbackstopjs 一起使用。

我必须解决的第一个问题是 Storybook 在每个页面的内部 <iframe> 元素内显示您的组件、降价和 prop-tables。这导致 backstopjs 出现问题,因为 CSS 作用域没有内部 <iframe> 内部 document 的概念。如果我的组件比直接 UI 中可见的大,那么它不会意识到内部 document 比外部长。除此之外,我无法为内部 <iframe> 内的任何组件设置任何 hideSelectorsremoveSelectors,因为它超出了范围。

因此,第一个有助于在其自己的页面上隔离内部 <iframe> 的重大发现是将 iframe.html 添加到 URL,如下所示(例如 - 假设您是运行 默认端口 localhost 上的 Storybook:

http://localhost:6006/iframe.html?selectedKind=...

这将以前内部的 <iframe> 隔离在其自己的页面上,而不会出现左侧菜单面板。因此,从这里开始,我现在可以根据需要隐藏和删除选择器,因为现在一切都在范围内。页面上显示的 Storybook markdown 和 prop-tables 很方便地位于单个 <div> 元素内。我用来指向这个 <div> 元素的唯一 CSS 选择器如下:

div[id="root"] > div > div > div[style*="font-family: -apple-system"]

所以我决定做的是在我的 backstop.json 配置文件中调用一个通用的 onReadyScript,而不是设置一个通用的选择器来捕获每个场景,如下所示:

{
  "id": "suite_name",
  "viewports": [
    ...
  ],
  "onReadyScript": "my-on-ready-script.js",
  "scenarios": [
    ...
  ],
  ...
}

然后,我的脚本被设置为删除 markdown 和 prop-tables <div> 元素,如下所示:

module.exports = async function (puppeteer) {
  /* Remove the markdown and prop tables from the Storybook preview panel */
  await puppeteer
    .$eval('div[id="root"] > div > div > div[style*="font-family: -apple-system"]', (markdownAndPropTables) => {
      markdownAndPropTables.parentNode.remove();
    });
};

这让我的组件在每个页面上完全独立显示,backstopjs,然后可以单独捕获该组件。

这是我找到的实现我的目标的最佳解决方案。我也把它作为其他人的潜在解决方案。希望其中有一些东西可以帮助其他人做我想做的同样的事情!