Q. E2Eテストで稀に要素が取得出来なくなり失敗する
Playwright で Next.js アプリの E2E テストを行なっていた。 ボタンを押すと開くモーダルの要素を取得しようとする箇所で、要素が取得される前にモーダルがなぜか閉じてしまうケースがあり、失敗してしまうケースがあった。
以下のような調査を行った。
- React DevTools を利用した再レンダリングと状態の監視
調査を行ったところ、useDelayOpen という名前の hooks から提供されている状態が期待される状態とズレていることがわかった。
useDelayOpen のコードは以下のようなものになっていた。明らかに怪しい、状態の競合を起こしそうなアンチパターンっぽいコードである。
tsx
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 を排除する変更を行い解決した。