0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

floating要素のあるコンポーネント(Dropdown)をStorybook・Chromaticでテストするときに詰まったところ

Posted at

はじめに

Dropdownコンポーネント実装のときにFloating UIのDropdownのようにトリガーボタンとfloating要素の構成にしましたが、そうすると親要素のStyleの影響を受けてfloating要素部分の表示が見切れてしまう等といった問題がありました。

その問題を解消するために、floatingする要素をコンポーネント外のbody直下などに配置して表示するように改修しました。

ただ挙動自体は正しく動作するようになりましたが、DOMの配置方法を変更したことでStorybookのインタラクションテストやChromaticのVisual Regression Testing(以下VRT)に支障が出たため、その内容と対処方法を共有します。

詰まったところと対処方法

1. インタラクションテストでfloating要素が見つからない

Storybookでインタラクションテストを行う際にplay関数を使用します。play関数は引数としてcanvasElementを受け取りますが、このcanvasElementにはstoryに描画するHTMLElementが入っています。

// 例
export const SampleStory: Story = {
  play: async ({ canvasElement }) => {
    const canvas = within(canvasElement);
    await userEvent.click(canvas.getByRole('button'));
    ...
  },
};

そのため今回のDropdownのfloating要素のように、body直下に配置した要素はcanvasElemetの中には含まれていません。
なので、以下のようにownerDcumentを使用してbody要素を取得し、そこからfloating要素を見つける必要があります。

export const SampleStory: Story = {
  play: async ({ canvasElement }) => {
    const canvas = within(canvasElement);
    // body要素取得
    const body = canvasElement.ownerDocument.body;
    // #TODO body要素以降も書いておく
  },
};

またその他に@storybook/testing-libraryが提供するscreenを使用しても、body直下の要素を取得することはできるようですが、以下のように警告が出ていたため、この方法は採用しませんでした。

You are using Testing Library's screen' object. Use ' within(canvasElement) instead.
More info:https://storybook.js.org/docs/react/essentials/interactions

2. フローティング要素がsnapshotされない

ChromaticでDropdownのVRTを行った際に、Dropdownコンポーネント内の要素(トリガーボタンなど)はsnapshotされましたが、フローティング要素が表示されているはずなのに写っていませんでした。

Chromaticの公式ドキュメントの以下のところに、フローティング要素が写っていない理由が書いてありました。
Why are components that render in a portal (tooltip, modal, popover, menu) getting cut off?

Chromaticがコンポーネントをsnapshotする際に、その写る領域は#storybook-rootのdiv要素(=canvasElement)の高さまでのようです。
なのでドキュメントに書いてあるとおり、storyのdecoratorでフローティング要素を含めた高さを指定しておくことで、見切れず撮影することができました。

export default {
  component: Dropdown,
  title: "Dropdown VRT",
  decorators: [
    (Story) => (
      // 高さを指定
      <div style={{ height: "300px" }}> 
        <DropdownStory />
      </div>
    ),
  ],
};

まとめ

  • body直下に要素を置いた場合の各テストの対応
    • StorybookのインタラクションテストではcanvasElement.ownerDocument.bodyでbody要素にアクセスできる
    • ChromaticのVRTでは、#storybook-rootのdiv要素分の高さまでしかsnaphotされないため、その他の要素も写したい場合はdecoratorで高さを指定する

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?