以下のような機能を持つアプリケーションがあるとする。
- ヘッダーのアイコンをクリックすると「運営者からのお知らせ」を Bootstrap の popover で開く(クリックのたびに open/close がトグルする)
- 未読の「お知らせ」がある場合は、ログイン後に popover を自動で開く
しかし機能のテストをしたところ、バグっていたとする。
- 未読の「お知らせ」があるのに、 popover が自動で開かない
- ヘッダーのアイコンをクリックしても popover を閉じられない(一瞬消えて、またすぐ開いてしまう)
こういうバグの調査をするのに Chrome DevTools の Enable paint flashing と Animation controls を使ってみた。
期待する動作
バグってる状態
Chrome DevTools の Enable paint flashing と Animation controls を有効にした状態
得られた知見と考察
- ページロード後に popover の領域が DOM rendering されてるっぽいことから、 popover が自動で開く機能が壊れたのではなく、 popover を自動で開く機能がダブって実行されてしまい、開いてすぐ閉じられてしまうため、「自動で開かない」ように見えているのだろう、と思われる。ここまでわかれば popover を開く処理の呼び出し元を順に調べていって、ダブって実行されうるコードパスを突き止めればよい。
- なお、実際に直したバグは、 Backbone.View インスタンスが
listenTo(this.collection, 'sync', 'showPopover')
などとしてる状態で collection.fetch() を二回呼び出していた、というものだった
- なお、実際に直したバグは、 Backbone.View インスタンスが
- クリック時に popover の領域が再 rendering されてるっぽいことから、 click イベントハンドラの中で popover を閉じる処理が実行されてしまっているのだろう、と思われる。ここまでわかれば click イベントハンドラ関数を調べればよい。
- 実際に直したバグは、「popover の外の領域をクリックしたとき popover を閉じる」という振る舞いを実現するために
document
に対して popover を閉じる click イベントハンドラを追加していたが、そのイベントハンドラの中で popover の open/close トグル処理をになっているアイコンの DOM 要素自身をクリックした場合が考慮されていなかったため、$(document).click
で一回、$(element).click
で一回の合計二回 popover をトグルする処理が呼ばれていた、というものだった
- 実際に直したバグは、「popover の外の領域をクリックしたとき popover を閉じる」という振る舞いを実現するために