11

I have a text input and i'm listening for the changes.

mycomponent.ts

ngOnInit() {
    this.searchInput = new Control();
    this.searchInput.valueChanges
        .distinctUntilChanged()
        .subscribe(newValue => this.search(newValue))
}
search(query) {
    // do something to search
}

mycomponent.html

<search-box>
    <input type="text" [ngFormControl]="searchInput" >
</search-box>

Running the application everything works fine, but i want to unit-test it.

So here's what i tried

mycomponent.spec.ts

beforeEach(done => {
    createComponent().then(fix => {
        cmpFixture = fix
        mockResponse()
        instance = cmpFixture.componentInstance
        cmpFixture.detectChanges();
        done();
    })
})
describe('on searching on the list', () => {
        let compiled, input
        beforeEach(() => {
            cmpFixture.detectChanges();
            compiled = cmpFixture.debugElement.nativeElement;
            spyOn(instance, 'search').and.callThrough()
            input = compiled.querySelector('search-box > input')
            input.value = 'fake-search-query'
            cmpFixture.detectChanges();
        })
        it('should call the .search() method', () => {
            expect(instance.search).toHaveBeenCalled()
        })
    })

Test fails as the .search() method is not called.

I guess i have to set the value in another way to have the test realize of the change but i really don't know how.

Anyone has ideas?

3 Answers 3

26

It might be a little bit late, but it seems that your code is not dispatching input event after setting input element value:

// ...    
input.value = 'fake-search-query';
input.dispatchEvent(new Event('input'));
cmpFixture.detectChanges();
// ...

Updating input html field from within an Angular 2 test

Sign up to request clarification or add additional context in comments.

Comments

0

Triggering the value change of FormControl is as simple as:

cmpFixture.debugElement.componentInstance.searchInput.setValue(newValue);

1 Comment

You are assuming that exposing input as public property is the right approach, but that is not.
0

Custom component with @input, subscriptions, two way data binding

If you got a custom component you would need further changes in your application to be able to successfully unit test your application

have a look at the gist here this will give you some idea https://gist.github.com/AikoPath/050ad0ffb91d628d4b10ef81736af386/raw/846c7bcfc54be8cce78eba8d12015bf749b91eee/@ViewChild(ComponentUnderTestComponent).js

More over complete reading over here carefully otherwise you can easily get confused again - https://betterprogramming.pub/testing-angular-components-with-input-3bd6c07cfaf6

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.