3

I have the following code in jasmine:

    it('should pass on writing secondvalue in the input', async(() => {

      const fixture=TestBed.createComponent(AppComponent);
      const app=fixture.debugElement.nativeElement.querySelector("input").getAttribute("value");
      expect(app).toContain("firstvalue");
      fixture.detectChanges();
      expect(app).toContain("secondvalue");

      }));

The problem is that as soon as I run the test, the test fails. I expect it to wait because of the detectChanges() but it doesn't.

How do I properly implement: Waiting for the second value input for the input and check if the value will be "secondvalue".

Shouldn't the fixture.detectChanges() act like a even-blocker, for instance that it waits for the input to be triggered when someone starts writing on it?

1 Answer 1

3

When you make a change to your component state, you run detectChanges so that the changes propagate.

For example,

pageTitle: string;
ngOnInit() {
    this.pageTitle = 'first title';
}

And in the template:

<h4>{{pageTitle}}</h4>

In the test:

const fixture = TestBed.createComponent(AppComponent);
const h4 = fixture.debugElement.query(By.css('h4'));

console.log(component.pageTitle); // 'first title'
console.log(h4.nativeElement.textContent); // ''
fixture.detectChanges(); // Propagates ngOnInit changes
console.log(h4.nativeElement.textContent); // 'first title'

component.pageTitle = 'second title'; // Here we change state
console.log(component.pageTitle); // 'second title'
console.log(h4.nativeElement.textContent); // 'first title'
fixture.detectChanges(); // Propagate changes
console.log(h4.nativeElement.textContent); // 'second title'

A typical use case is checking things that depend on state, like having in template:

<div id="xxx" *ngIf="over18">Restricted content</div>

in component:

over18: boolean = false;

in test:

it('should show restricted content if over 18', () => {
    component.over18 = true; // change state from the default one
    fixture.detectChanges(); // propagate changes to view

    // now we can actually test
    const divElem = fixture.debugElement.query(By.css('div#xxx')); // would be null if not shown in DOM
    expect(divElem).toBeTruthy();
});

Note that I'm testing component logic. Checking that if I type "asdf" into input its value is going to update is, in my opinion, out of unit testing scope- this functionality is provided by HTML standard/ Angular team.

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

4 Comments

You mean I explicitly have to put the new value right? It can be put inside the input from the karma runner?
@masterach You most likely need to call fixture.detectChanges() before testing the values. Also, it is not very clear, what your component looks like, and how are the values changed in there.
Shouldn't const h4 = fixture.debugElement.query(By.css('h4')); be: const h2 = fixture.debugElement.query(By.css('h2'));
@AndersPersson it should, although the example itself was hopefully clear enough anyway. Thanks for noticing, I've updated the answer. You could also submit edits yourself and wait for people to approve your suggested changes instead of leaving a comment.

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.