From 674708e92e6a930f9f824cc8816f777d522f85c9 Mon Sep 17 00:00:00 2001 From: anandtiwary <52081890+anandtiwary@users.noreply.github.com> Date: Thu, 21 Jan 2021 10:48:58 -0800 Subject: [PATCH 1/2] fix: adding debounce subscription on component init --- .../search-box/search-box.component.test.ts | 68 +++++++++++++++++++ .../src/search-box/search-box.component.ts | 26 ++++--- 2 files changed, 85 insertions(+), 9 deletions(-) create mode 100644 projects/components/src/search-box/search-box.component.test.ts diff --git a/projects/components/src/search-box/search-box.component.test.ts b/projects/components/src/search-box/search-box.component.test.ts new file mode 100644 index 000000000..1e9fed024 --- /dev/null +++ b/projects/components/src/search-box/search-box.component.test.ts @@ -0,0 +1,68 @@ +import { Subject } from 'rxjs'; +import { fakeAsync } from '@angular/core/testing'; +import { createHostFactory, Spectator } from '@ngneat/spectator/jest'; +import { SearchBoxComponent } from './search-box.component'; +import { By } from '@angular/platform-browser'; +import { runFakeRxjs } from '@hypertrace/test-utils'; + +describe('Search box Component', () => { + let spectator: Spectator; + + const createHost = createHostFactory({ + component: SearchBoxComponent, + shallow: true + }); + + test('should work with default values', fakeAsync(() => { + // const onValueChangeSpy = jest.fn(); + const valueSubject = new Subject(); + spectator = createHost( + ``, + { + hostProps: { + placeholder: 'Test Placeholder', + onValueChange: (value: string) => { + valueSubject.next(value); + } + } + } + ); + + const inputDebugElement = spectator.debugElement.query(By.css('input')); + spectator.component.value = 'Test'; + spectator.triggerEventHandler(inputDebugElement, 'input', spectator.component.value); + spectator.tick(); + // spectator.tick(); + + valueSubject.subscribe({ + next: (value: string) => { + console.log(value); + } + }); + + // expect(onValueChangeSpy).toHaveBeenCalledWith('Test'); + + runFakeRxjs(({ expectObservable }) => { + spectator.triggerEventHandler(inputDebugElement, 'input', spectator.component.value); + spectator.tick(); + expectObservable(spectator.component.valueChange).toBe('(xyz)', { + x: 'Test' + }); + }); + })); + + // test('should pass properties to Mat Slide toggle correctly', fakeAsync(() => { + // const onValueChangeSpy = jest.fn(); + // spectator = createHost( + // ``, + // { + // hostProps: { + // placeholder: 'Test Placeholder', + // value: '', + // debounceTime: 10, + // onValueChange: onValueChangeSpy + // } + // } + // ); + // })); +}); diff --git a/projects/components/src/search-box/search-box.component.ts b/projects/components/src/search-box/search-box.component.ts index 6efb532a5..939ffad98 100644 --- a/projects/components/src/search-box/search-box.component.ts +++ b/projects/components/src/search-box/search-box.component.ts @@ -1,4 +1,4 @@ -import { ChangeDetectionStrategy, Component, EventEmitter, Input, OnChanges, Output } from '@angular/core'; +import { ChangeDetectionStrategy, Component, EventEmitter, Input, OnChanges, OnInit, Output } from '@angular/core'; import { IconType } from '@hypertrace/assets-library'; import { SubscriptionLifecycle, TypedSimpleChanges } from '@hypertrace/common'; import { Subject } from 'rxjs'; @@ -33,7 +33,7 @@ import { IconSize } from '../icon/icon-size'; ` }) -export class SearchBoxComponent implements OnChanges { +export class SearchBoxComponent implements OnInit, OnChanges { @Input() public placeholder: string = 'Search'; @@ -41,7 +41,7 @@ export class SearchBoxComponent implements OnChanges { public value: string = ''; @Input() - public debounceTime: number = 0; + public debounceTime?: number; @Output() public readonly valueChange: EventEmitter = new EventEmitter(); @@ -55,14 +55,13 @@ export class SearchBoxComponent implements OnChanges { public isFocused: boolean = false; private readonly debouncedValueSubject: Subject = new Subject(); + public ngOnInit(): void { + this.setDebouncedSubscription(); + } + public ngOnChanges(changes: TypedSimpleChanges): void { if (changes.debounceTime) { - this.subscriptionLifecycle.unsubscribe(); - this.subscriptionLifecycle.add( - this.debouncedValueSubject - .pipe(debounceTime(this.debounceTime)) - .subscribe(value => this.valueChange.emit(value)) - ); + this.setDebouncedSubscription(); } } @@ -82,4 +81,13 @@ export class SearchBoxComponent implements OnChanges { this.value = ''; this.onValueChange(); } + + private setDebouncedSubscription(): void { + this.subscriptionLifecycle.unsubscribe(); + this.subscriptionLifecycle.add( + this.debouncedValueSubject + .pipe(debounceTime(this.debounceTime ?? 0)) + .subscribe(value => this.valueChange.emit(value)) + ); + } } From acfb18b7bba24579276527e7b82fac00dca5afe2 Mon Sep 17 00:00:00 2001 From: anandtiwary <52081890+anandtiwary@users.noreply.github.com> Date: Thu, 21 Jan 2021 11:35:41 -0800 Subject: [PATCH 2/2] refactor: add tests --- .../search-box/search-box.component.test.ts | 65 +++++++++---------- 1 file changed, 30 insertions(+), 35 deletions(-) diff --git a/projects/components/src/search-box/search-box.component.test.ts b/projects/components/src/search-box/search-box.component.test.ts index 1e9fed024..1e315de13 100644 --- a/projects/components/src/search-box/search-box.component.test.ts +++ b/projects/components/src/search-box/search-box.component.test.ts @@ -1,9 +1,8 @@ -import { Subject } from 'rxjs'; import { fakeAsync } from '@angular/core/testing'; -import { createHostFactory, Spectator } from '@ngneat/spectator/jest'; -import { SearchBoxComponent } from './search-box.component'; import { By } from '@angular/platform-browser'; import { runFakeRxjs } from '@hypertrace/test-utils'; +import { createHostFactory, Spectator } from '@ngneat/spectator/jest'; +import { SearchBoxComponent } from './search-box.component'; describe('Search box Component', () => { let spectator: Spectator; @@ -14,55 +13,51 @@ describe('Search box Component', () => { }); test('should work with default values', fakeAsync(() => { - // const onValueChangeSpy = jest.fn(); - const valueSubject = new Subject(); spectator = createHost( ``, { hostProps: { - placeholder: 'Test Placeholder', - onValueChange: (value: string) => { - valueSubject.next(value); - } + placeholder: 'Test Placeholder' } } ); const inputDebugElement = spectator.debugElement.query(By.css('input')); + expect((inputDebugElement.nativeElement as HTMLInputElement)?.placeholder).toEqual('Test Placeholder'); spectator.component.value = 'Test'; - spectator.triggerEventHandler(inputDebugElement, 'input', spectator.component.value); - spectator.tick(); - // spectator.tick(); - valueSubject.subscribe({ - next: (value: string) => { - console.log(value); - } + runFakeRxjs(({ expectObservable }) => { + expectObservable(spectator.component.valueChange).toBe('x', { + x: 'Test' + }); + + spectator.triggerEventHandler(inputDebugElement, 'input', spectator.component.value); + spectator.tick(); }); + })); - // expect(onValueChangeSpy).toHaveBeenCalledWith('Test'); + test('should work with arbitrary debounce time', fakeAsync(() => { + spectator = createHost( + ``, + { + hostProps: { + placeholder: 'Test Placeholder', + debounceTime: 200 + } + } + ); + + const inputDebugElement = spectator.debugElement.query(By.css('input')); + expect((inputDebugElement.nativeElement as HTMLInputElement)?.placeholder).toEqual('Test Placeholder'); + spectator.component.value = 'Test2'; runFakeRxjs(({ expectObservable }) => { + expectObservable(spectator.component.valueChange).toBe('200ms x', { + x: 'Test2' + }); + spectator.triggerEventHandler(inputDebugElement, 'input', spectator.component.value); spectator.tick(); - expectObservable(spectator.component.valueChange).toBe('(xyz)', { - x: 'Test' - }); }); })); - - // test('should pass properties to Mat Slide toggle correctly', fakeAsync(() => { - // const onValueChangeSpy = jest.fn(); - // spectator = createHost( - // ``, - // { - // hostProps: { - // placeholder: 'Test Placeholder', - // value: '', - // debounceTime: 10, - // onValueChange: onValueChangeSpy - // } - // } - // ); - // })); });