How to test rendering a bound value in a razor based test into a non blazor component. #1282
-
Hi all, var inputElement = cut.Find("input");
inputElement.Input("John"); and test if the bound property was changed correctly. This works. var pElement = cut.Find("p");
pElement.MarkupMatches("<p>John</p>"); // Fails I asked this question initially on Stack Overflow. I got an anwer that it is possible, and I was asked to head over to this repo. Question But here are is the most relevant content: My Model public class Person
{
public string Firstname { get; set; } = null!;
public string Lastname { get; set; } = null!;
} My custom input component <div>
<label>@(Label??"Missing Label")
<input type="text" @bind-value="InputValue" @bind-value:event="oninput" />
</label>
</div>
@code {
private string _value = null!;
/// <summary>
/// Gets or sets the value of the components input control.
/// </summary>
public string InputValue
{
get => this._value;
set => this.Value = value;
}
/// <summary>
/// Gets or sets the label for the input.
/// </summary>
[Parameter]
public string Label { get; set; } = null!;
/// <summary>
/// Gets or sets the bound value-canged event.
/// </summary>
[Parameter]
public EventCallback<string> ValueChanged { get; set; }
/// <summary>
/// Gets or sets the bound value of the component.
/// </summary>
[Parameter]
public string Value
{
get
{
return this._value;
}
set
{
var changed = (value is null ^ this._value is null)||(value != this._value);
this._value = value!;
if (changed)
{
this.InvokeAsync(() =>
{
this.ValueChanged.InvokeAsync(this._value);
this.StateHasChanged();
});
}
}
}
} And here, the most important part @using Bunit
@using Bunit.Rendering;
@using Microsoft.AspNetCore.Components.Forms
@using NUnit.Framework;
@using Microsoft.AspNetCore.Components;
@using Microsoft.Extensions.DependencyInjection;
@using BlazorDemo.Model;
@using BlazorDemo.Components;
@inherits Bunit.TestContext;
@code {
[Test]
public void TestMyInputComponent()
{
var testModel = new Person();
var editCtx = new EditContext(testModel);
var cut = Render(
@<div>
<EditForm EditContext="editCtx">
<MyCustomInputComponent Label="Firstname" @bind-Value="testModel.Firstname"></MyCustomInputComponent>
</EditForm>
<p>@testModel.Firstname</p>
</div>
);
var inputElement = cut.Find("input");
inputElement.Input("John");
// Passes
Assert.That(testModel.Firstname, Is.EqualTo("John"));
var pElement = cut.Find("p");
// Fails
pElement.MarkupMatches("<p>John</p>");
}
} Thank you. |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 2 replies
-
Thanks for providing the bigger picture - now with some more details, yes the way you try to achieve that isn't really working (for maybe not obvious reasons). Your call to To make your scenario work, you can refactor all the content inside var cut = Render(@<FormComponent></FormComponent>); Or if you need the strongly typed var cut = Render<FormComponent>(@<FormComponent></FormComponent>); That will make your test immediately! Now - why doesn't the original version work out of the box. As said earlier, we use a type called @egil We might want to make it more clear in the docs, that |
Beta Was this translation helpful? Give feedback.
Thanks for providing the bigger picture - now with some more details, yes the way you try to achieve that isn't really working (for maybe not obvious reasons).
Your call to
cut.Render(@</>)
will, as you noticed on SO, also create aIRenderedComponent<IComponent>
. The component is from bUnit.To make your scenario work, you can refactor all the content inside
Render
in its own (test)component. And call the test like that:Or if you need the strongly typed
IRenderedComponent<T>
:That will make your test immediately!
Now - why doesn't the original version work out of the box…