Skip to content

Commit 824495f

Browse files
committed
refactor(header): signal inputs, host bindings, cleanup, tests
1 parent 40b4c9a commit 824495f

File tree

9 files changed

+87
-54
lines changed

9 files changed

+87
-54
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,19 @@
11
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
2-
import { RouterTestingModule } from '@angular/router/testing';
3-
import { Router } from '@angular/router';
42

53
import { HeaderBrandComponent } from './header-brand.component';
64

75
describe('HeaderBrandComponent', () => {
86
let component: HeaderBrandComponent;
97
let fixture: ComponentFixture<HeaderBrandComponent>;
10-
let router: Router;
118

129
beforeEach(waitForAsync(() => {
1310
TestBed.configureTestingModule({
14-
imports: [RouterTestingModule.withRoutes([]), HeaderBrandComponent]
11+
imports: [HeaderBrandComponent]
1512
}).compileComponents();
1613
}));
1714

1815
beforeEach(() => {
1916
fixture = TestBed.createComponent(HeaderBrandComponent);
20-
router = TestBed.inject(Router);
2117
component = fixture.componentInstance;
2218
fixture.detectChanges();
2319
});
@@ -29,4 +25,8 @@ describe('HeaderBrandComponent', () => {
2925
it('should have css classes', () => {
3026
expect(fixture.nativeElement).toHaveClass('header-brand');
3127
});
28+
29+
it('should have role', () => {
30+
expect(fixture.nativeElement.getAttribute('role')).toBe('button');
31+
});
3232
});
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
1-
import { Component, HostBinding, Input } from '@angular/core';
1+
import { Component, input } from '@angular/core';
22

33
@Component({
44
selector: 'c-header-brand',
5-
template: '<ng-content />'
5+
template: '<ng-content />',
6+
exportAs: 'cHeaderBrand',
7+
host: {
8+
'[attr.role]': 'role()',
9+
class: 'header-brand'
10+
}
611
})
712
export class HeaderBrandComponent {
813
/**
914
* Default role for header-brand. [docs]
10-
* @type string
15+
* @return string
1116
* @default 'button'
1217
*/
13-
@HostBinding('attr.role')
14-
@Input()
15-
role = 'button';
16-
17-
@HostBinding('class.header-brand') headerBrandClass = true;
18+
readonly role = input('button');
1819
}
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
import { Component, HostBinding } from '@angular/core';
1+
import { Component } from '@angular/core';
22

33
@Component({
44
selector: 'c-header-divider, [cHeaderDivider]',
5-
template: ``
5+
template: ``,
6+
host: {
7+
class: 'header-divider'
8+
}
69
})
7-
export class HeaderDividerComponent {
8-
@HostBinding('class.header-divider') headerDividerClass = true;
9-
}
10+
export class HeaderDividerComponent {}

projects/coreui-angular/src/lib/header/header-nav/header-nav.component.spec.ts

+5-2
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,7 @@ describe('HeaderNavComponent', () => {
99
beforeEach(async () => {
1010
await TestBed.configureTestingModule({
1111
imports: [HeaderNavComponent]
12-
})
13-
.compileComponents();
12+
}).compileComponents();
1413
});
1514

1615
beforeEach(() => {
@@ -26,4 +25,8 @@ describe('HeaderNavComponent', () => {
2625
it('should have css classes', () => {
2726
expect(fixture.nativeElement).toHaveClass('header-nav');
2827
});
28+
29+
it('should have role', () => {
30+
expect(fixture.nativeElement.getAttribute('role')).toBe('navigation');
31+
});
2932
});
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,20 @@
1-
import { Component, HostBinding, Input } from '@angular/core';
1+
import { Component, input } from '@angular/core';
22

33
@Component({
44
selector: 'c-header-nav',
55
template: '<ng-content />',
6-
styleUrls: ['./header-nav.component.scss']
6+
styleUrls: ['./header-nav.component.scss'],
7+
exportAs: 'cHeaderNav',
8+
host: {
9+
'[attr.role]': 'role()',
10+
class: 'header-nav'
11+
}
712
})
813
export class HeaderNavComponent {
914
/**
1015
* Default role for header-nav. [docs]
11-
* @type string
16+
* @return string
1217
* @default 'navigation'
1318
*/
14-
@HostBinding('attr.role')
15-
@Input()
16-
role = 'navigation';
17-
18-
@HostBinding('class.header-nav') headerNavClass = true;
19+
readonly role = input('navigation');
1920
}
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
import { Component, HostBinding } from '@angular/core';
1+
import { Component } from '@angular/core';
22

33
@Component({
44
selector: 'c-header-text, [cHeaderText]',
5-
template: '<ng-content />'
5+
template: '<ng-content />',
6+
host: {
7+
class: 'header-text'
8+
}
69
})
7-
export class HeaderTextComponent {
8-
@HostBinding('class.header-text') headerTextClass = true;
9-
}
10+
export class HeaderTextComponent {}
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,31 @@
1-
import { TestBed } from '@angular/core/testing';
2-
import { ElementRef, Renderer2 } from '@angular/core';
1+
import { ComponentFixture, TestBed } from '@angular/core/testing';
2+
import { Component, DebugElement, ElementRef, Renderer2 } from '@angular/core';
3+
import { By } from '@angular/platform-browser';
34

45
import { HeaderTogglerDirective } from './header-toggler.directive';
56

7+
@Component({
8+
imports: [HeaderTogglerDirective],
9+
template: '<div cHeaderToggler></div>'
10+
})
11+
export class TestComponent {
12+
theme!: 'dark' | 'light' | undefined;
13+
}
14+
615
class MockElementRef extends ElementRef {}
716

817
describe('HeaderTogglerDirective', () => {
18+
let fixture: ComponentFixture<TestComponent>;
19+
let debugElement: DebugElement;
20+
921
beforeEach(() => {
1022
TestBed.configureTestingModule({
23+
imports: [TestComponent],
1124
providers: [Renderer2, { provide: ElementRef, useClass: MockElementRef }]
1225
});
26+
fixture = TestBed.createComponent(TestComponent);
27+
debugElement = fixture.debugElement.query(By.directive(HeaderTogglerDirective));
28+
fixture.detectChanges();
1329
});
1430

1531
it('should create an instance', () => {
@@ -18,4 +34,13 @@ describe('HeaderTogglerDirective', () => {
1834
expect(directive).toBeTruthy();
1935
});
2036
});
37+
38+
it('should have css class', () => {
39+
expect(debugElement.nativeElement).toHaveClass('header-toggler');
40+
});
41+
42+
it('should set attributes', () => {
43+
expect(debugElement.nativeElement.getAttribute('type')).toBe('button');
44+
expect(debugElement.nativeElement.getAttribute('aria-label')).toBe('Toggle navigation');
45+
});
2146
});

projects/coreui-angular/src/lib/header/header-toggler/header-toggler.directive.ts

+15-15
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,31 @@
1-
import { AfterContentInit, Directive, ElementRef, HostBinding, inject, Input, Renderer2 } from '@angular/core';
1+
import { AfterContentInit, Directive, ElementRef, inject, input, Renderer2 } from '@angular/core';
22

33
@Directive({
4-
selector: '[cHeaderToggler]'
4+
selector: '[cHeaderToggler]',
5+
exportAs: 'cHeaderToggler',
6+
host: {
7+
'[attr.type]': 'type()',
8+
'[attr.aria-label]': 'ariaLabel()',
9+
class: 'header-toggler'
10+
}
511
})
612
export class HeaderTogglerDirective implements AfterContentInit {
713
readonly #renderer = inject(Renderer2);
814
readonly #hostElement = inject(ElementRef);
915

10-
@HostBinding('class.header-toggler') headerToggler = true;
1116
/**
12-
* Default role for header-toggler. [docs]
13-
* @type string
17+
* Default type for header-toggler button. [docs]
18+
* @return string
1419
* @default 'button'
1520
*/
16-
@HostBinding('attr.type')
17-
@Input()
18-
type = 'button';
21+
readonly type = input('button');
22+
1923
/**
2024
* Default aria-label attr for header-toggler. [docs]
2125
* @type string
2226
* @default 'Toggle navigation'
2327
*/
24-
@HostBinding('attr.aria-label')
25-
@Input()
26-
ariaLabel = 'Toggle navigation';
27-
28-
#hasContent!: boolean;
28+
readonly ariaLabel = input('Toggle navigation');
2929

3030
addDefaultIcon(): void {
3131
const span = this.#renderer.createElement('span');
@@ -34,8 +34,8 @@ export class HeaderTogglerDirective implements AfterContentInit {
3434
}
3535

3636
ngAfterContentInit(): void {
37-
this.#hasContent = this.#hostElement.nativeElement.childNodes.length > 0;
38-
if (!this.#hasContent) {
37+
const hasContent = this.#hostElement.nativeElement.childNodes.length > 0;
38+
if (!hasContent) {
3939
this.addDefaultIcon();
4040
}
4141
}

projects/coreui-angular/src/lib/header/header/header.component.ts

+5-4
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,11 @@ import { Positions } from '../../coreui.types';
66
type Container = boolean | 'sm' | 'md' | 'lg' | 'xl' | 'xxl' | 'fluid';
77

88
@Component({
9-
selector: 'c-header, [c-header]',
10-
templateUrl: './header.component.html',
11-
imports: [NgClass],
12-
host: { '[attr.role]': 'role()', '[class]': 'hostClasses()' }
9+
selector: 'c-header, [c-header]',
10+
templateUrl: './header.component.html',
11+
imports: [NgClass],
12+
exportAs: 'cHeader',
13+
host: { '[attr.role]': 'role()', '[class]': 'hostClasses()' }
1314
})
1415
export class HeaderComponent {
1516
/**

0 commit comments

Comments
 (0)