Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit a3c1448

Browse files
committed
fix(core): cleanup timeout on popover close
- Added tests to ensure that the popover cancels delayed showing when it receives an 'interest' event or a 'hide-popover' command before the delay completes Signed-off-by: Cory Rylan <[email protected]>
1 parent 878bafb commit a3c1448

2 files changed

Lines changed: 50 additions & 0 deletions

File tree

projects/core/src/internal/controllers/type-native-popover.controller.test.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -811,6 +811,48 @@ describe('type-popover.controller - interest invoker support', () => {
811811
await new Promise(r => setTimeout(r, 60));
812812
expect(element.matches(':popover-open')).toBe(false);
813813
});
814+
815+
it('should cancel delayed show when the popover closes before delay completes', async () => {
816+
element.openDelay = 50;
817+
await elementIsStable(element);
818+
819+
const open = untilEvent(element, 'open');
820+
element.showPopover();
821+
expect(await open).toBeDefined();
822+
823+
const interestEvent = new Event('interest', { cancelable: true }) as Event & { source: HTMLElement };
824+
interestEvent.source = button;
825+
element.dispatchEvent(interestEvent);
826+
await elementIsStable(element);
827+
828+
const close = untilEvent(element, 'close');
829+
element.hidePopover();
830+
expect(await close).toBeDefined();
831+
832+
await new Promise(r => setTimeout(r, 60));
833+
expect(element.matches(':popover-open')).toBe(false);
834+
});
835+
836+
it('should cancel delayed show when the popover receives hide-popover before delay completes', async () => {
837+
element.openDelay = 50;
838+
await elementIsStable(element);
839+
840+
const open = untilEvent(element, 'open');
841+
element.showPopover();
842+
expect(await open).toBeDefined();
843+
844+
const interestEvent = new Event('interest', { cancelable: true }) as Event & { source: HTMLElement };
845+
interestEvent.source = button;
846+
element.dispatchEvent(interestEvent);
847+
await elementIsStable(element);
848+
849+
const close = untilEvent(element, 'close');
850+
element.dispatchEvent(new CommandEvent('command', { command: 'hide-popover', source: button }));
851+
expect(await close).toBeDefined();
852+
853+
await new Promise(r => setTimeout(r, 60));
854+
expect(element.matches(':popover-open')).toBe(false);
855+
});
814856
});
815857

816858
describe('type-popover.controller - showPopover source fallback', () => {

projects/core/src/internal/controllers/type-native-popover.controller.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,10 @@ export class TypeNativePopoverController<T extends NativePopover> implements Rea
9696
setTimeout(() => this.host.hidePopover(), this.host.closeTimeout);
9797
}
9898

99+
if (e.newState === 'closed') {
100+
this.#clearInterestTimeout();
101+
}
102+
99103
this.host.inert = this.host.matches(':not(:popover-open)');
100104

101105
if (this.host.modal) {
@@ -119,6 +123,7 @@ export class TypeNativePopoverController<T extends NativePopover> implements Rea
119123

120124
if (e.command === 'hide-popover') {
121125
this.host.hidePopover();
126+
this.#clearInterestTimeout();
122127
}
123128

124129
if (e.command === 'show-popover') {
@@ -167,7 +172,10 @@ export class TypeNativePopoverController<T extends NativePopover> implements Rea
167172

168173
hostDisconnected() {
169174
this.#observers.forEach(observer => observer.disconnect());
175+
this.#clearInterestTimeout();
176+
}
170177

178+
#clearInterestTimeout() {
171179
if (this.#interestTimeout) {
172180
clearTimeout(this.#interestTimeout);
173181
this.#interestTimeout = null;

0 commit comments

Comments
 (0)