I have a test that is failing because, in the test environment, a button is not disabled when it should be. I am able to reproduce this using this simple code:
<form #submissionForm="ngForm" novalidate>
<input
type="text"
ngModel
required
id="questionAnswer"
name="questionAnswer"
>
{{ submissionForm.valid }}
<button [disabled]="!submissionForm.valid">Submit</button>
</form>
Within the test, submissionForm.valid
is true
; however, in the running code it correctly reports as false
.
Here is an example of the test: https://stackblitz.com/edit/angular-testing-with-jasmine-mnbymr?file=app/app.component.html
And here is a running app: https://stackblitz.com/edit/angular-v9uxvt?file=src/app/app.component.html
Note that I haven't added the it()
in the stack blitz example - what I'd like to know is why is valid
true in one app and false
in the other?
CodePudding user response:
I'll start off by saying that I don't fully understand what is actually going on here. Here is what I do know.
Template-driven forms are asynchronous. This can make testing a little bit tougher with template-driven forms because you have to take that factor into account (one of the reasons some people always prefer to use reactive forms). In my experience fixture.whenStable()
has been helpful:
fixture.whenStable()
Get a promise that resolves when the fixture is stable. This can be used to resume testing after events have triggered asynchronous activity or asynchronous change detection.
Basically, you can put your code that tests the template-driven form inside of fixture.whenStable().then()
and the form is guaranteed to be initialized and ready for interaction.
Here is an updated stack blitz with the test functioning correctly.
This SO post is helpful to understand a bit more about what is going on.