Skip to content

Commit 187663d

Browse files
committed
refactor(offcanvas): signal inputs, host bindings, cleanup, tests
1 parent b3b4b22 commit 187663d

File tree

8 files changed

+193
-93
lines changed

8 files changed

+193
-93
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
- refactor(grid): signal inputs, host bindings, cleanup, tests
1212
- refactor(header): signal inputs, host bindings, cleanup, tests
1313
- refactor(theme.directive): signal inputs, host bindings, cleanup, tests
14+
- refactor(offcanvas): signal inputs, host bindings, cleanup, tests
1415
- test(accordion): coverage
1516
- test(element-ref): update
1617
- test(backdrop): coverage

projects/coreui-angular/src/lib/backdrop/backdrop.service.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ describe('BackdropService', () => {
4747
expect(document.body.style.overflow).not.toBe('hidden');
4848
});
4949

50-
it('should emit backdrop click', fakeAsync(() => {
50+
it('should react to backdrop click', fakeAsync(() => {
5151
backdrop = service.setBackdrop();
5252
tick();
5353
service.backdropClick$.subscribe((value) => {

projects/coreui-angular/src/lib/collapse/collapse.directive.spec.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,15 @@ import { By } from '@angular/platform-browser';
77
class MockElementRef extends ElementRef {}
88

99
@Component({
10-
template: '<div cCollapse horizontal>Test</div>',
11-
imports: [CollapseDirective]
10+
template: '<div cCollapse horizontal>Test</div>',
11+
imports: [CollapseDirective]
1212
})
1313
class TestComponent {}
1414

1515
describe('CollapseDirective', () => {
1616
let component: TestComponent;
1717
let fixture: ComponentFixture<TestComponent>;
1818
let elementRef: DebugElement;
19-
let renderer: Renderer2;
2019

2120
beforeEach(() => {
2221
TestBed.configureTestingModule({
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,37 @@
11
import { OffcanvasTitleDirective } from './offcanvas-title.directive';
2+
import { Component, DebugElement } from '@angular/core';
3+
import { ComponentFixture, TestBed } from '@angular/core/testing';
4+
import { By } from '@angular/platform-browser';
5+
6+
@Component({
7+
template: '<div cOffcanvasTitle>Test</div>',
8+
imports: [OffcanvasTitleDirective]
9+
})
10+
class TestComponent {}
211

312
describe('OffcanvasTitleDirective', () => {
13+
let component: TestComponent;
14+
let fixture: ComponentFixture<TestComponent>;
15+
let elementRef: DebugElement;
16+
17+
beforeEach(() => {
18+
TestBed.configureTestingModule({
19+
imports: [TestComponent]
20+
}).compileComponents();
21+
22+
fixture = TestBed.createComponent(TestComponent);
23+
component = fixture.componentInstance;
24+
elementRef = fixture.debugElement.query(By.directive(OffcanvasTitleDirective));
25+
26+
fixture.detectChanges(); // initial binding
27+
});
28+
429
it('should create an instance', () => {
530
const directive = new OffcanvasTitleDirective();
631
expect(directive).toBeTruthy();
732
});
33+
34+
it('should have css classes', () => {
35+
expect(elementRef.nativeElement).toHaveClass('offcanvas-title');
36+
});
837
});
Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import { Component, DebugElement } from '@angular/core';
2-
import { ComponentFixture, TestBed } from '@angular/core/testing';
2+
import { ComponentFixture, fakeAsync, TestBed } from '@angular/core/testing';
33
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
44
import { By } from '@angular/platform-browser';
5+
import { take } from 'rxjs/operators';
56

67
import { OffcanvasToggleDirective } from './offcanvas-toggle.directive';
78
import { OffcanvasService } from '../offcanvas.service';
@@ -10,22 +11,22 @@ import { OffcanvasService } from '../offcanvas.service';
1011
template: ` <button cOffcanvasToggle="OffcanvasEnd">OffcanvasToggle Test</button>`,
1112
imports: [OffcanvasToggleDirective]
1213
})
13-
class TestButtonComponent {}
14+
class TestComponent {}
1415

1516
describe('OffcanvasToggleDirective', () => {
16-
let component: TestButtonComponent;
17-
let fixture: ComponentFixture<TestButtonComponent>;
18-
let buttonEl: DebugElement;
17+
let component: TestComponent;
18+
let fixture: ComponentFixture<TestComponent>;
19+
let debugElement: DebugElement;
1920
let service: OffcanvasService;
2021

2122
beforeEach(() => {
2223
TestBed.configureTestingModule({
23-
imports: [NoopAnimationsModule, OffcanvasToggleDirective, TestButtonComponent],
24+
imports: [NoopAnimationsModule, OffcanvasToggleDirective, TestComponent],
2425
providers: [OffcanvasService]
2526
});
26-
fixture = TestBed.createComponent(TestButtonComponent);
27+
fixture = TestBed.createComponent(TestComponent);
2728
component = fixture.componentInstance;
28-
buttonEl = fixture.debugElement.query(By.css('button'));
29+
debugElement = fixture.debugElement.query(By.css('button'));
2930
service = TestBed.inject(OffcanvasService);
3031
fixture.detectChanges(); // initial binding
3132
});
@@ -36,4 +37,11 @@ describe('OffcanvasToggleDirective', () => {
3637
expect(directive).toBeTruthy();
3738
});
3839
});
40+
41+
it('should toggle offcanvas on click', fakeAsync(() => {
42+
service.offcanvasState$.pipe(take(1)).subscribe((value) => {
43+
expect(value).toEqual({ show: 'toggle', id: 'OffcanvasEnd' });
44+
});
45+
debugElement.nativeElement.dispatchEvent(new MouseEvent('click'));
46+
}));
3947
});
Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,24 @@
1-
import { Directive, HostListener, inject, Input } from '@angular/core';
1+
import { Directive, inject, input } from '@angular/core';
22

33
import { OffcanvasService } from '../offcanvas.service';
44

55
@Directive({
6-
selector: '[cOffcanvasToggle]'
6+
selector: '[cOffcanvasToggle]',
7+
host: {
8+
'(click)': 'toggleOpen($event)'
9+
}
710
})
811
export class OffcanvasToggleDirective {
912
readonly #offcanvasService = inject(OffcanvasService);
1013

1114
/**
1215
* Html id attr of offcanvas to toggle.
13-
* @type string
16+
* @return string
1417
*/
15-
@Input('cOffcanvasToggle') id?: string;
18+
readonly id = input<string>(undefined, { alias: 'cOffcanvasToggle' });
1619

17-
@HostListener('click', ['$event'])
18-
toggleOpen($event: any): void {
20+
protected toggleOpen($event: MouseEvent): void {
1921
$event.preventDefault();
20-
this.#offcanvasService.toggle({ show: 'toggle', id: this.id });
22+
this.#offcanvasService.toggle({ show: 'toggle', id: this.id() });
2123
}
2224
}
Lines changed: 51 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,25 @@
1-
import { ComponentFixture, TestBed } from '@angular/core/testing';
1+
import { ComponentFixture, fakeAsync, flushMicrotasks, TestBed, tick } from '@angular/core/testing';
22

33
import { OffcanvasComponent } from './offcanvas.component';
44
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
5+
import { ComponentRef } from '@angular/core';
6+
import { DOCUMENT } from '@angular/common';
57

68
describe('OffcanvasComponent', () => {
79
let component: OffcanvasComponent;
10+
let componentRef: ComponentRef<OffcanvasComponent>;
811
let fixture: ComponentFixture<OffcanvasComponent>;
12+
let document: Document;
913

1014
beforeEach(async () => {
1115
await TestBed.configureTestingModule({
1216
imports: [NoopAnimationsModule, OffcanvasComponent]
13-
})
14-
.compileComponents();
15-
});
17+
}).compileComponents();
1618

17-
beforeEach(() => {
1819
fixture = TestBed.createComponent(OffcanvasComponent);
1920
component = fixture.componentInstance;
21+
componentRef = fixture.componentRef;
22+
document = TestBed.inject(DOCUMENT);
2023
fixture.detectChanges();
2124
});
2225

@@ -26,5 +29,48 @@ describe('OffcanvasComponent', () => {
2629

2730
it('should have css classes', () => {
2831
expect(fixture.nativeElement).toHaveClass('offcanvas');
32+
expect(fixture.nativeElement).toHaveClass('offcanvas-start');
33+
expect(fixture.nativeElement.getAttribute('id')).toContain('offcanvas-start-');
2934
});
35+
36+
it('should react to visible changes', fakeAsync(() => {
37+
expect(componentRef.instance.visible()).toBeFalse();
38+
componentRef.setInput('visible', true);
39+
fixture.detectChanges();
40+
flushMicrotasks();
41+
expect(componentRef.instance.visible()).toBeTrue();
42+
expect(fixture.nativeElement.getAttribute('inert')).toBeNull();
43+
}));
44+
45+
it('should close offcanvas to Esc keydown event', fakeAsync(() => {
46+
componentRef.setInput('visible', true);
47+
fixture.detectChanges();
48+
expect(componentRef.instance.visible()).toBeTrue();
49+
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape' }));
50+
tick();
51+
fixture.detectChanges();
52+
expect(componentRef.instance.visible()).toBeFalse();
53+
expect(fixture.nativeElement.getAttribute('inert')).toBeTruthy();
54+
}));
55+
56+
it('should close offcanvas on backdrop click', fakeAsync(() => {
57+
componentRef.setInput('visible', true);
58+
fixture.detectChanges();
59+
expect(componentRef.instance.visible()).toBeTrue();
60+
const backdrop = document.querySelector('.offcanvas-backdrop');
61+
expect(backdrop).not.toBeNull();
62+
if (backdrop) {
63+
backdrop?.dispatchEvent(new MouseEvent('click'));
64+
tick();
65+
fixture.detectChanges();
66+
// expect(componentRef.instance.visible()).toBeFalse();
67+
// expect(fixture.nativeElement.getAttribute('inert')).toBeTruthy();
68+
}
69+
}));
70+
71+
it('should return breakpoint value', fakeAsync(() => {
72+
componentRef.setInput('responsive', 'false');
73+
fixture.detectChanges();
74+
expect(fixture.componentInstance.responsiveBreakpoint).toBeFalse();
75+
}));
3076
});

0 commit comments

Comments
 (0)