This was working and now does not. This is for a pretty simple page. I use DevExpress and emailTextBox
is a DxTextBox
.
This is successful
var emailTextBox = allTextBoxes.Single(x => x.Instance.InputId == "email");
emailTextBox.TextEditChange("");
button.Click();
var li = renderedComponent.Find("li.validation-message");
Assert.NotNull(li);
Assert.Equal("Your Email is required", li.InnerHtml);
Assert.Equal("", pageModel.Email);
Then this code immediately follows - and fails.
emailTextBox.TextEditChange("bogus");
button.Click();
li = renderedComponent.Find("li.validation-message");
Assert.NotNull(li);
Assert.Equal("The Email field is not a valid e-mail address.", li.InnerHtml);
Assert.Equal("bogus", pageModel.Email);
The problems are:
- The error message it finds is the message for an empty field.
pageModel.Email
is "".- In the debugger I look at
emailTextBox.Text
and it is "".
Is TextEditChange()
not the right way to set the value in DxTextBox
?
Update:
And sometimes randomly the above 2nd test passes, but then the next test, which is similar, fails. These tests assume that not only the <input>
value is being set, but that the <DataAnnotationsValidator/>
and <ValidationSummary/>
have then run.
Update 2:
The following works:
emailTextBox.TextEditChange("bogus");
button.Click();
renderedComponent.Render();
li = renderedComponent.Find("li.validation-message");
Assert.NotNull(li);
Assert.Equal("The Email field is not a valid e-mail address.", li.InnerHtml);
Assert.Equal("bogus", pageModel.Email);
Is it required to call renderedComponent.Render()
after the TextEditChange/Click?
I got a lot of help from the bUnit team on this and the fundamental answer is twofold.
First, I need to make each
TextEditChange()
&Click()
test a separate unit test. Doing several in a row is asking for trouble because the page elements all stay the same and it's just the text that changes.Second, do a
WaitFor
, usually on therenderedComponent.Find()
with a timeout. The unit test thereby tests for the expected change not by asserting the value, but by throwing an exception if the expected change does not get rendered before the timeout.