2

I have an app where I change the value of an input and it should immediately change the value of an h1. It works well when tested manually (changing the input changes the h1), but it's not working from a test (changing the input has no effect on the content of the h1).

I've double checked I'm invoking detectChanges and whenStable when I think I should, but still I've got no luck.

Can someone spot what I'm doing wrong?

app.component.ts

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-root',
  template: `
    <form>
      <input type="text" name="query-input" [(ngModel)]="myText" />
    </form>
    <h1>H1 content is "{{myText}}"</h1>
  `
})
export class AppComponent implements OnInit {
  public myText = 'Default value';

  ngOnInit(): void {
    this.myText = 'Value from ngOnInit';
  }
}

app.component.spec.ts

import { TestBed, async } from '@angular/core/testing';
import { AppComponent } from './app.component';
import { FormsModule } from '@angular/forms';

describe('AppComponent', () => {
  beforeEach(async(() => {
    TestBed.configureTestingModule({
      imports: [
        FormsModule
      ],
      declarations: [
        AppComponent
      ],
    }).compileComponents();
  }));

  it('should work', () => {
    const fixture = TestBed.createComponent(AppComponent);
    console.log(fixture.componentInstance.myText); // VALUE IS OK: "Default value"
    fixture.detectChanges();
    fixture.whenStable().then(() => {
      console.log(fixture.componentInstance.myText); // VALUE IS OK: "Value from ngOnInit"
      const compiled = fixture.debugElement.nativeElement;
      compiled.querySelector('input').value = 'Value from test';
      fixture.detectChanges();
      fixture.whenStable().then(() => {
        console.log(compiled.querySelector('input').value); // VALUE IS OK: 'Value from test'
        console.log(fixture.componentInstance.myText); // VALUE IS UNEXPECTED: 'Value from ngOnInit'
        console.log(compiled.querySelector('h1').textContent); // VALUE IS UNEXPECTED: 'H1 content is "Value from ngOnInit"'
      });
    });
  });
});

So in those 2 last console.log I'm getting Value from ngOnInit but I expected to get Value from test

Angular version used: 7.2.0

1 Answer 1

3

Found the issue, it's not enough to change the value of the input, one needs to invoke dispatchEvent afterwards.

So this code:

  ...
  compiled.querySelector('input').value = 'Value from test';
  fixture.detectChanges();
  ...

Needed to be changed to:

  ...
  compiled.querySelector('input').value = 'Value from test';
  compiled.querySelector('input').dispatchEvent(new Event('input'));
  fixture.detectChanges();
  ...

Note:

If the previous solution doesn't work for you, try sending the blur event after the input. I hit one case in which input was not enough.

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

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.