Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 57 additions & 0 deletions projects/coreui-angular/src/lib/popover/popover.directive.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { DirectiveFixture, TestBed } from '@angular/core/testing';
import { expect, vi } from 'vitest';
import { PopoverDirective } from './popover.directive';
import { Triggers } from '../coreui.types';
import { UIDService } from '../services';

describe('PopoverDirective', () => {
let visible: WritableSignal<boolean>;
Expand Down Expand Up @@ -73,6 +74,62 @@ describe('PopoverDirective', () => {
expect(fixture.nativeElement.hasAttribute('aria-describedby')).toBe(false);
});

it('should not describe the host when hidden before the popover shows', async () => {
visible.set(true);
fixture.detectChanges();
await vi.advanceTimersByTimeAsync(50);
visible.set(false);
fixture.detectChanges();
await vi.advanceTimersByTimeAsync(1000);
fixture.detectChanges();
expect(fixture.nativeElement.hasAttribute('aria-describedby')).toBe(false);
expect(document.querySelector('.popover')).toBeNull();
});

it('should not run the show timer when destroyed before the popover shows', async () => {
const getUID = vi.spyOn(TestBed.inject(UIDService), 'getUID');
visible.set(true);
fixture.detectChanges();
await vi.advanceTimersByTimeAsync(50);
fixture.destroy();
await vi.advanceTimersByTimeAsync(1000);
expect(getUID).not.toHaveBeenCalled();
});

it('should leave no pending timers when destroyed while the popover hides', async () => {
visible.set(true);
fixture.detectChanges();
await vi.runAllTimersAsync();
visible.set(false);
fixture.detectChanges();
await vi.advanceTimersByTimeAsync(50);
fixture.destroy();
await vi.advanceTimersByTimeAsync(0);
expect(vi.getTimerCount()).toBe(0);
});

it.each([
['before', 50],
['after', 1000]
])('should not describe the host when the content empties %s the popover shows', async (_, elapsed) => {
fixture.destroy();
const content = signal('content');
fixture = TestBed.createDirective(PopoverDirective, {
tagName: 'button',
bindings: [inputBinding('cPopover', content), twoWayBinding('cPopoverVisible', visible)]
});
fixture.autoDetectChanges();
visible.set(true);
fixture.detectChanges();
await vi.advanceTimersByTimeAsync(elapsed);
content.set('');
fixture.detectChanges();
await vi.advanceTimersByTimeAsync(1000);
fixture.detectChanges();
expect(fixture.nativeElement.hasAttribute('aria-describedby')).toBe(false);
expect(document.querySelector('.popover')).toBeNull();
});

it('should set popover on and off', async () => {
fixture.autoDetectChanges();
visible.set(false);
Expand Down
5 changes: 5 additions & 0 deletions projects/coreui-angular/src/lib/popover/popover.directive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,9 @@ export class PopoverDirective implements OnDestroy, OnInit, AfterViewInit {
}

private destroyTooltipElement(): void {
clearTimeout(this.#timerId1);
clearTimeout(this.#timerId2);
this.tooltipId = '';
this.tooltip?.remove();
this.tooltipRef?.destroy();
// @ts-ignore
Expand All @@ -225,6 +228,7 @@ export class PopoverDirective implements OnDestroy, OnInit, AfterViewInit {
private addTooltipElement(): void {
if (!this.content()) {
this.destroyTooltipElement();
this.#changeDetectorRef.markForCheck();
return;
}

Expand Down Expand Up @@ -261,6 +265,7 @@ export class PopoverDirective implements OnDestroy, OnInit, AfterViewInit {
}

private removeTooltipElement(): void {
clearTimeout(this.#timerId1);
this.tooltipId = '';
if (!this.tooltipRef) {
return;
Expand Down
57 changes: 57 additions & 0 deletions projects/coreui-angular/src/lib/tooltip/tooltip.directive.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { DirectiveFixture, TestBed } from '@angular/core/testing';
import { expect, vi } from 'vitest';
import { TooltipDirective } from './tooltip.directive';
import { Triggers } from '../coreui.types';
import { UIDService } from '../services';

describe('TooltipDirective', () => {
let visible: WritableSignal<boolean>;
Expand Down Expand Up @@ -73,6 +74,62 @@ describe('TooltipDirective', () => {
expect(fixture.nativeElement.hasAttribute('aria-describedby')).toBe(false);
});

it('should not describe the host when hidden before the tooltip shows', async () => {
visible.set(true);
fixture.detectChanges();
await vi.advanceTimersByTimeAsync(50);
visible.set(false);
fixture.detectChanges();
await vi.advanceTimersByTimeAsync(1000);
fixture.detectChanges();
expect(fixture.nativeElement.hasAttribute('aria-describedby')).toBe(false);
expect(document.querySelector('.tooltip')).toBeNull();
});

it('should not run the show timer when destroyed before the tooltip shows', async () => {
const getUID = vi.spyOn(TestBed.inject(UIDService), 'getUID');
visible.set(true);
fixture.detectChanges();
await vi.advanceTimersByTimeAsync(50);
fixture.destroy();
await vi.advanceTimersByTimeAsync(1000);
expect(getUID).not.toHaveBeenCalled();
});

it('should leave no pending timers when destroyed while the tooltip hides', async () => {
visible.set(true);
fixture.detectChanges();
await vi.runAllTimersAsync();
visible.set(false);
fixture.detectChanges();
await vi.advanceTimersByTimeAsync(50);
fixture.destroy();
await vi.advanceTimersByTimeAsync(0);
expect(vi.getTimerCount()).toBe(0);
});

it.each([
['before', 50],
['after', 1000]
])('should not describe the host when the content empties %s the tooltip shows', async (_, elapsed) => {
fixture.destroy();
const content = signal('content');
fixture = TestBed.createDirective(TooltipDirective, {
tagName: 'button',
bindings: [inputBinding('cTooltip', content), twoWayBinding('cTooltipVisible', visible)]
});
fixture.autoDetectChanges();
visible.set(true);
fixture.detectChanges();
await vi.advanceTimersByTimeAsync(elapsed);
content.set('');
fixture.detectChanges();
await vi.advanceTimersByTimeAsync(1000);
fixture.detectChanges();
expect(fixture.nativeElement.hasAttribute('aria-describedby')).toBe(false);
expect(document.querySelector('.tooltip')).toBeNull();
});

it('should set popover on and off', async () => {
fixture.autoDetectChanges();
visible.set(false);
Expand Down
5 changes: 5 additions & 0 deletions projects/coreui-angular/src/lib/tooltip/tooltip.directive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,9 @@ export class TooltipDirective implements OnDestroy, OnInit, AfterViewInit {
}

private destroyTooltipElement(): void {
clearTimeout(this.#timerId1);
clearTimeout(this.#timerId2);
this.tooltipId = '';
this.tooltip?.remove();
this.tooltipRef?.destroy();
// @ts-ignore
Expand All @@ -223,6 +226,7 @@ export class TooltipDirective implements OnDestroy, OnInit, AfterViewInit {
private addTooltipElement(): void {
if (!this.content()) {
this.destroyTooltipElement();
this.#changeDetectorRef.markForCheck();
return;
}

Expand Down Expand Up @@ -259,6 +263,7 @@ export class TooltipDirective implements OnDestroy, OnInit, AfterViewInit {
}

private removeTooltipElement(): void {
clearTimeout(this.#timerId1);
this.tooltipId = '';
if (!this.tooltipRef) {
return;
Expand Down
Loading