2 <meta charset=
"utf-8" />
3 <title>The popover-hide-delay CSS property
</title>
4 <link rel=
"author" href=
"mailto:masonf@chromium.org">
5 <link rel=help
href=
"https://open-ui.org/components/popover.research.explainer">
6 <meta name=
"timeout" content=
"long">
7 <script src=
"/resources/testharness.js"></script>
8 <script src=
"/resources/testharnessreport.js"></script>
9 <script src=
"/resources/testdriver.js"></script>
10 <script src=
"/resources/testdriver-actions.js"></script>
11 <script src=
"/resources/testdriver-vendor.js"></script>
12 <script src=
"resources/popover-utils.js"></script>
17 popover-hide-delay:
100ms;
19 [popovertargetaction=hover] {
21 popover-show-delay:
100ms;
23 #unrelated {top:
300px;}
25 /* Fixed position everything to ensure nothing overlaps */
29 <div id=unrelated
>Unrelated element
</div>
31 <div popover id=example1
>Popover
</div>
32 <button popovertarget=example1 popovertargetaction=hover id=invoker1
>Hover me
</button>
35 const hoverDelays
= 100; // This needs to match the style block above.
36 const hoverWaitTime
= 200; // How long to wait to cover the delay for sure.
38 // NOTE about testing methodology:
39 // This test checks whether popovers are hidden *after* the appropriate de-hover
40 // delay. The delay used for testing is kept low, to avoid this test taking too
41 // long, but that means that sometimes on a slow bot/client, the delay can
42 // elapse before we are able to check the popover status. And that can make this
43 // test flaky. To avoid that, the msSinceMouseOver() function is used to check
44 // that not-too-much time has passed, and if it has, the test is simply skipped.
46 const unrelated
= document
.getElementById('unrelated');
48 function getComputedStyleTimeMs(element
,property
) {
49 // Times are in seconds, so just strip off the 's'.
50 return Number(getComputedStyle(element
)[property
].slice(0,-1))*1000;
53 promise_test(async (t
) => {
54 await
mouseOver(unrelated
);
55 const popover
= document
.getElementById('example1');
56 assert_false(popover
.matches(':popover-open'));
57 popover
.showPopover();
58 assert_true(popover
.matches(':popover-open'));
59 await
waitForHoverTime(hoverWaitTime
);
60 assert_false(popover
.matches(':popover-open'));
61 assert_true(msSinceMouseOver() >= hoverWaitTime
,'waitForHoverTime should wait the specified time');
62 assert_true(hoverWaitTime
> hoverDelays
,'hoverDelays is the value from CSS, hoverWaitTime should be longer than that');
63 assert_equals(getComputedStyleTimeMs(invoker1
,'popoverShowDelay'),hoverDelays
,'popover-show-delay is incorrect');
64 assert_equals(getComputedStyleTimeMs(popover
,'popoverHideDelay'),hoverDelays
,'popover-hide-delay is incorrect');
65 },`The popover-hide-delay causes a popover to be hidden after a delay`);
67 promise_test(async (t
) => {
68 await
mouseOver(unrelated
);
69 const popover
= document
.getElementById('example1');
70 assert_false(popover
.matches(':popover-open'));
71 popover
.showPopover();
72 await
mouseOver(popover
);
73 await
waitForHoverTime(hoverWaitTime
);
74 assert_true(popover
.matches(':popover-open'),'hovering the popover should keep it showing');
75 await
mouseOver(unrelated
);
76 let showing
= popover
.matches(':popover-open');
77 if (msSinceMouseOver() >= hoverDelays
)
78 return; // The WPT runner was too slow.
79 assert_true(showing
,'hovering unrelated element shouldn\'t immediately hide the popover');
80 await
waitForHoverTime(hoverWaitTime
);
81 assert_false(popover
.matches(':popover-open'),'hovering unrelated element should hide popover after delay');
82 },`hovering the popover keeps it from being hidden`);
84 promise_test(async (t
) => {
85 await
mouseOver(unrelated
);
86 const popover
= document
.getElementById('example1');
87 const invoker
= document
.getElementById('invoker1');
88 assert_false(popover
.matches(':popover-open'));
89 await
mouseOver(invoker
);
90 await
waitForHoverTime(hoverWaitTime
);
91 assert_true(popover
.matches(':popover-open'));
92 await
waitForHoverTime(hoverWaitTime
);
93 assert_true(popover
.matches(':popover-open'),'While still hovering the invoker, popover should not be hidden');
94 await
mouseOver(popover
);
95 await
waitForHoverTime(hoverWaitTime
);
96 await
mouseOver(invoker
);
97 await
waitForHoverTime(hoverWaitTime
);
98 assert_true(popover
.matches(':popover-open'),'Moving hover between invoker and popover should keep popover from being hidden');
99 await
mouseOver(unrelated
);
100 await
waitForHoverTime(hoverWaitTime
);
101 assert_false(popover
.matches(':popover-open'),'Moving hover to unrelated should finally hide the popover');
102 },`hovering a popovertargetaction=hover invoking element keeps the popover from being hidden`);
106 <div popover id=example2
>Popover
</div>
107 <button popovertarget=example2 popovertargetaction=toggle
><span><span data-note=nested_element id=invoker2
>Click me
</span></span></button>
110 promise_test(async (t
) => {
111 await
mouseOver(unrelated
);
112 const popover
= document
.getElementById('example2');
113 const invoker
= document
.getElementById('invoker2');
114 assert_equals(getComputedStyleTimeMs(popover
,'popoverHideDelay'),hoverDelays
,'popover-hide-delay is incorrect');
115 assert_false(popover
.matches(':popover-open'));
116 await
mouseOver(invoker
);
117 popover
.showPopover();
118 await
waitForHoverTime(hoverWaitTime
);
119 assert_true(popover
.matches(':popover-open'),'While hovering an invoker element, popover should not be hidden');
120 await
mouseOver(popover
);
121 await
waitForHoverTime(hoverWaitTime
);
122 await
mouseOver(invoker
);
123 await
waitForHoverTime(hoverWaitTime
);
124 assert_true(popover
.matches(':popover-open'),'Moving hover between invoker and popover should keep popover from being hidden');
125 await
mouseOver(unrelated
);
126 await
waitForHoverTime(hoverWaitTime
);
127 assert_false(popover
.matches(':popover-open'),'Moving hover to unrelated should finally hide the popover');
128 },`hovering a popovertargetaction=toggle invoking element keeps the popover from being hidden`);