Tooltip hover bug fix – test added and changelog updated
この PR は、ツールチップが HTML コンテンツ上で誤って閉じてしまうバグに対し、回帰テストを追加し、変更内容を CHANGELOG に記録したものです。
背景
<wa-tooltip> の handleMouseOut が this.anchor?.matches(':hover') と this.matches(':hover') に依存していたため、マウスポインタがホスト要素からスロット内子要素へ移動する際に :hover が偽になるケースがありました。この挙動は #2507 として報告され、#2512 で根本的に修正されました。PR #2516 は、その修正が正しく機能することをテストで保証し、リリースノートに反映させることを目的としています。
技術的な変更
CHANGELOG の更新
packages/webawesome/docs/docs/resources/changelog.md に、次のエントリが追加されました。
- Fixed a bug in `<wa-tooltip>` that caused the tooltip to hide when hovering over HTML content [pr:2512]
この一行の追加により、公開パッケージの変更履歴にバグ修正が明示され、利用者はアップデートの理由を容易に把握できます。
テストコードの拡充
テストファイル tooltip.test.ts で主に 2 か所が変更されています。
@@ -4,7 +4,7 @@ import { html } from 'lit';
import sinon from 'sinon';
import { expectEvent } from '../../internal/test/expect-event.js';
import { fixtures } from '../../internal/test/fixture.js';
-import { clickOnElement } from '../../internal/test/pointer-utilities.js';
+import { clickOnElement, moveMouseOnElement } from '../../internal/test/pointer-utilities.js';
@@ -447,23 +447,32 @@ describe('<wa-tooltip>', () => {
<wa-tooltip for="hover-child-btn" trigger="hover" show-delay="0" hide-delay="0">
- <a href="#" id="tooltip-link">A link inside the tooltip</a>
+ <a href="#" id="tooltip-link" style="display: inline-block; padding: 1rem;">A link inside the tooltip</a>
</wa-tooltip>
</div>
`);
const tooltip = el.querySelector<WaTooltip>('wa-tooltip')!;
+ const anchor = el.querySelector<HTMLElement>('#hover-child-btn')!;
const childLink = el.querySelector<HTMLElement>('#tooltip-link')!;
- tooltip.open = true;
+ // Open the tooltip by hovering its anchor, so a real pointer is positioned over the trigger.
+ await moveMouseOnElement(anchor);
await waitUntil(() => tooltip.open);
expect(tooltip.open).to.be.true;
- // Simulate the pointer moving off of the tooltip host and onto a slotted child element.
- // relatedTarget is the element the pointer is moving to, which is how browsers report this.
- tooltip.dispatchEvent(new MouseEvent('mouseout', { relatedTarget: childLink, bubbles: true }));
- await aTimeout(50);
+ // Move the pointer off the anchor and onto a slotted child element of the tooltip. This generates a real
+ // `mouseout` whose `relatedTarget` is the slotted child, which the tooltip should recognize as "still within me"
+ // and stay open.
+ await moveMouseOnElement(childLink);
+ await aTimeout(tooltip.hideDelay + 50);
expect(tooltip.open).to.be.true;
+
+ // Move the pointer fully away and confirm it now hides, proving the test isn't a false positive.
+ await moveMouseOnElement(document.body, 'top', 0, 0);
+ await waitUntil(() => !tooltip.open);
+ expect(tooltip.open).to.be.false;
});
});
moveMouseOnElement を利用することで、実ブラウザの mouseout が持つ relatedTarget を自然に取得でき、handleMouseOut の新ロジックが期待通りに動作することを検証しています。
設計判断
テストで synthetic MouseEvent が relatedTarget を設定できないことが判明したため、実際のポインタ移動をシミュレートするユーティリティ moveMouseOnElement を採用しました。この選択は、テストがブラウザ固有のマウスイベント挙動を忠実に再現できるようにし、回帰テストの信頼性を高める設計判断といえます。また、CHANGELOG へのエントリはシンプルな箇条書きで追加することで、リリースノートの一貫性と可読性を維持しています。
まとめ
PR #2516 は、ツールチップの hover バグ修正を 自動テストで保証 し、CHANGELOG に記録 することで、品質と公開情報の両面でプロダクトの信頼性を向上させます。テスト実装に実際のポインタ操作を組み込む判断は、ブラウザ挙動の正確な検証を可能にし、将来的な UI 変更に対する回帰テストの有効性を高めています。