O hirunewani blog

Q. E2Eテストで稀に要素が取得出来なくなり失敗する

Created at

Playwrightを利用したE2Eテストで稀に要素が取得できなくなり失敗すると相談を受けた際の対応についてまとめた。

PlaywrightでNext.jsアプリのE2Eテストを行なっていた。 ボタンを押すと開くモーダルの要素を取得しようとする箇所で、要素が取得される前にモーダルがなぜか閉じてしまうケースがあり、失敗してしまうケースがあった。

以下のような調査を行った。

  • React DevToolsを利用した再レンダリングと状態の監視

調査を行ったところ、useDelayOpenという名前のhooksから提供されている状態が期待される状態とズレていることがわかった。

useDelayOpenのコードは以下のようなものになっていた。明らかに怪しい、状態の競合を起こしそうなアンチパターンっぽいコードである。

const useDelayOpen = (next?: boolean) => {
  const [open, setOpen] = useState(next);
  const [leave, setLeave] = useState(false);
  const id = useRef<number>();
  useEffect(() => {
    if (next) {
      setOpen(next);
    } else {
      setLeave(true);
      id.current = window.setTimeout(() => {
        setOpen(false);
        setLeave(false);
      }, 250);
    }
    return () => {
      if (id.current) {
        window.clearTimeout(id.current);
        id.current = undefined;
      }
    };
  }, [next]);
  return [open, leave] as const;
};

コードを読んだところ、そもそもCSSアニメーションと同期するためのコードだったようなので、onAnimationEndからアニメーションの終了を取るようにして、useEffectやtimeoutを排除する変更を行い解決した。