Skip to content

Commit 10a8bef

Browse files
committed
fix: 🐛 type check on component outputs
Allow subjects as component output ✅ Closes: ngneat#689
1 parent bfd6ad5 commit 10a8bef

File tree

4 files changed

+92
-8
lines changed

4 files changed

+92
-8
lines changed

projects/spectator/jest/test/function-output/function-output.component.spec.ts

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,30 @@ describe('FunctionOutputComponent', () => {
1414
});
1515

1616
it('should emit the event on button click', () => {
17-
let output;
17+
let output = false;
1818
spectator.output('buttonClick').subscribe((result) => (output = result));
1919

2020
spectator.click('button');
2121

2222
expect(output).toEqual(true);
2323
});
24+
25+
it('should emit the event on button click - EventEmitter', () => {
26+
let output = false;
27+
spectator.output('buttonClickedEvent').subscribe((result) => (output = result));
28+
29+
spectator.click('button');
30+
31+
expect(output).toEqual(true);
32+
});
33+
34+
it('should emit the event on button click - Subject', () => {
35+
let output = false;
36+
spectator.output('buttonClickedSubject').subscribe((result) => (output = result));
37+
spectator.click('button');
38+
39+
expect(output).toEqual(true);
40+
});
2441
});
2542

2643
describe('with SpectatorHost', () => {
@@ -36,12 +53,30 @@ describe('FunctionOutputComponent', () => {
3653
});
3754

3855
it('should emit the event on button click', () => {
39-
let output;
56+
let output = false;
4057
host.output('buttonClick').subscribe((result) => (output = result));
4158

4259
host.click('button');
4360

4461
expect(output).toEqual(true);
4562
});
63+
64+
it('should emit the event on button click - EventEmitter', () => {
65+
let output = false;
66+
host.output('buttonClickedEvent').subscribe((result) => (output = result));
67+
68+
host.click('button');
69+
70+
expect(output).toEqual(true);
71+
});
72+
73+
it('should emit the event on button click - Subject', () => {
74+
let output = false;
75+
host.output('buttonClickedSubject').subscribe((result) => (output = result));
76+
77+
host.click('button');
78+
79+
expect(output).toEqual(true);
80+
});
4681
});
4782
});

projects/spectator/src/lib/base/dom-spectator.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { DebugElement, ElementRef, EventEmitter, OutputEmitterRef, Type } from '@angular/core';
22
import { ComponentFixture, tick } from '@angular/core/testing';
33
import { By } from '@angular/platform-browser';
4-
import { Observable } from 'rxjs';
4+
import { Observable, Subject } from 'rxjs';
55

66
import { dispatchFakeEvent, dispatchKeyboardEvent, dispatchMouseEvent, dispatchTouchEvent } from '../dispatch-events';
77
import { DOMSelector } from '../dom-selectors';
@@ -20,7 +20,7 @@ const KEY_UP = 'keyup';
2020

2121
type KeysMatchingReturnType<T, V> = keyof { [P in keyof T as T[P] extends V ? P : never]: P } & keyof T;
2222
type KeysMatchingOutputFunction<T> = KeysMatchingReturnType<T, OutputEmitterRef<any>>;
23-
type KeysMatchingClassicOutput<T> = KeysMatchingReturnType<T, EventEmitter<any>>;
23+
type KeysMatchingClassicOutput<T> = KeysMatchingReturnType<T, EventEmitter<any> | Subject<any>>;
2424
type KeysMatchingOutput<T> = KeysMatchingOutputFunction<T> | KeysMatchingClassicOutput<T>;
2525

2626
/**

projects/spectator/test/function-output/function-output.component.spec.ts

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { createComponentFactory, createHostFactory, Spectator, SpectatorHost } from '@ngneat/spectator';
22
import { FunctionOutputComponent } from './function-output.component';
3+
import { fakeAsync, tick } from '@angular/core/testing';
34

45
describe('FunctionOutputComponent', () => {
56
describe('with Spectator', () => {
@@ -14,13 +15,30 @@ describe('FunctionOutputComponent', () => {
1415
});
1516

1617
it('should emit the event on button click', () => {
17-
let output;
18+
let output = false;
1819
spectator.output('buttonClick').subscribe((result) => (output = result));
1920

2021
spectator.click('button');
2122

2223
expect(output).toEqual(true);
2324
});
25+
26+
it('should emit the event on button click - EventEmitter', () => {
27+
let output = false;
28+
spectator.output('buttonClickedEvent').subscribe((result) => (output = result));
29+
30+
spectator.click('button');
31+
32+
expect(output).toEqual(true);
33+
});
34+
35+
it('should emit the event on button click - Subject', () => {
36+
let output = false;
37+
spectator.output('buttonClickedSubject').subscribe((result) => (output = result));
38+
spectator.click('button');
39+
40+
expect(output).toEqual(true);
41+
});
2442
});
2543

2644
describe('with SpectatorHost', () => {
@@ -36,12 +54,30 @@ describe('FunctionOutputComponent', () => {
3654
});
3755

3856
it('should emit the event on button click', () => {
39-
let output;
57+
let output = false;
4058
host.output('buttonClick').subscribe((result) => (output = result));
4159

4260
host.click('button');
4361

4462
expect(output).toEqual(true);
4563
});
64+
65+
it('should emit the event on button click - EventEmitter', () => {
66+
let output = false;
67+
host.output('buttonClickedEvent').subscribe((result) => (output = result));
68+
69+
host.click('button');
70+
71+
expect(output).toEqual(true);
72+
});
73+
74+
it('should emit the event on button click - Subject', () => {
75+
let output = false;
76+
host.output('buttonClickedSubject').subscribe((result) => (output = result));
77+
78+
host.click('button');
79+
80+
expect(output).toEqual(true);
81+
});
4682
});
4783
});
Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,23 @@
1-
import { Component, input, output, ɵINPUT_SIGNAL_BRAND_WRITE_TYPE } from '@angular/core';
1+
import { Component, EventEmitter, input, Output, output, ɵINPUT_SIGNAL_BRAND_WRITE_TYPE } from '@angular/core';
2+
import { ReplaySubject } from 'rxjs';
23

34
@Component({
45
selector: 'app-function-output',
5-
template: ` <button (click)="buttonClick.emit(true)">Emit function output</button> `,
6+
template: ` <button (click)="buttonClicked()">Emit function output</button> `,
67
standalone: true,
78
})
89
export class FunctionOutputComponent {
910
public buttonClick = output<boolean>();
11+
12+
@Output()
13+
public buttonClickedEvent = new EventEmitter<boolean>();
14+
15+
@Output()
16+
public buttonClickedSubject = new ReplaySubject<boolean>();
17+
18+
protected buttonClicked(): void {
19+
this.buttonClick.emit(true);
20+
this.buttonClickedEvent.emit(true);
21+
this.buttonClickedSubject.next(true);
22+
}
1023
}

0 commit comments

Comments
 (0)