Files
sufi-blazor/tests/Components/Forms/SbFormFieldTests.cs
T
2026-05-18 15:53:59 +03:30

232 lines
6.7 KiB
C#

using Bunit;
using SufiChain.SufiBlazor.Components.Forms;
using Xunit;
namespace SufiChain.SufiBlazor.Tests.Components.Forms;
public class SbFormFieldTests : BunitContext
{
private IRenderedComponent<SbFormField> RenderFormField(
Action<ComponentParameterCollectionBuilder<SbFormField>>? configure = null)
{
return Render<SbFormField>(p =>
{
p.AddChildContent("<input type=\"text\" />");
configure?.Invoke(p);
});
}
[Fact]
public void RendersFormFieldStructure()
{
// Arrange & Act
var cut = RenderFormField();
// Assert
var wrapper = cut.Find(".sb-form-field");
Assert.NotNull(wrapper);
Assert.NotNull(cut.Find(".sb-form-field__input"));
}
[Fact]
public void RendersChildContent()
{
// Arrange & Act
var cut = RenderFormField();
// Assert
var inputWrapper = cut.Find(".sb-form-field__input");
Assert.NotNull(inputWrapper);
Assert.NotNull(cut.Find("input[type='text']"));
}
[Fact]
public void RendersLabelWhenProvided()
{
// Arrange & Act
var cut = RenderFormField(p => p
.Add(x => x.Label, "Email")
.Add(x => x.InputId, "email"));
// Assert
var label = cut.Find(".sb-form-field__label");
Assert.NotNull(label);
Assert.Contains("Email", label.TextContent);
}
[Fact]
public void DoesNotRenderLabelWhenEmpty()
{
// Arrange & Act
var cut = RenderFormField();
// Assert
Assert.Empty(cut.FindAll(".sb-form-field__label"));
}
[Fact]
public void RendersRequiredIndicatorWhenRequiredTrue()
{
// Arrange & Act
var cut = RenderFormField(p => p
.Add(x => x.Label, "Name")
.Add(x => x.Required, true));
// Assert
var requiredSpan = cut.Find(".sb-form-field__required");
Assert.NotNull(requiredSpan);
Assert.Equal("*", requiredSpan.TextContent);
Assert.Equal("true", requiredSpan.GetAttribute("aria-hidden"));
}
[Fact]
public void DoesNotRenderRequiredIndicatorWhenRequiredFalse()
{
// Arrange & Act
var cut = RenderFormField(p => p
.Add(x => x.Label, "Name")
.Add(x => x.Required, false));
// Assert
Assert.Empty(cut.FindAll(".sb-form-field__required"));
}
[Fact]
public void AssociatesLabelWithInputId()
{
// Arrange & Act
var cut = RenderFormField(p => p
.Add(x => x.Label, "Username")
.Add(x => x.InputId, "username-field"));
// Assert
var label = cut.Find("label.sb-form-field__label");
Assert.Equal("username-field", label.GetAttribute("for"));
}
[Fact]
public void RendersHelperTextWhenProvided()
{
// Arrange & Act
var cut = RenderFormField(p => p
.Add(x => x.HelperText, "We'll never share your email")
.Add(x => x.InputId, "email"));
// Assert
var helper = cut.Find(".sb-form-field__helper");
Assert.NotNull(helper);
Assert.Contains("We'll never share your email", helper.TextContent);
}
[Fact]
public void DoesNotRenderHelperTextWhenErrorTextPresent()
{
// Arrange & Act - ErrorText takes precedence, helper is hidden
var cut = RenderFormField(p => p
.Add(x => x.HelperText, "Helper text")
.Add(x => x.ErrorText, "This field is invalid")
.Add(x => x.InputId, "field"));
// Assert
Assert.Empty(cut.FindAll(".sb-form-field__helper"));
}
[Fact]
public void RendersErrorTextWhenProvided()
{
// Arrange & Act
var cut = RenderFormField(p => p
.Add(x => x.ErrorText, "Email is required")
.Add(x => x.InputId, "email"));
// Assert
var error = cut.Find(".sb-form-field__error");
Assert.NotNull(error);
Assert.Contains("Email is required", error.TextContent);
Assert.Equal("alert", error.GetAttribute("role"));
}
[Fact]
public void AppliesErrorClassWhenErrorTextPresent()
{
// Arrange & Act
var cut = RenderFormField(p => p.Add(x => x.ErrorText, "Invalid"));
// Assert
var wrapper = cut.Find(".sb-form-field");
Assert.Contains("sb-form-field--error", wrapper.ClassList);
}
[Fact]
public void AppliesDisabledClassWhenDisabledTrue()
{
// Arrange & Act
var cut = RenderFormField(p => p.Add(x => x.Disabled, true));
// Assert
var wrapper = cut.Find(".sb-form-field");
Assert.Contains("sb-form-field--disabled", wrapper.ClassList);
}
[Fact]
public void AppliesClassParameter()
{
// Arrange & Act
var cut = RenderFormField(p => p.Add(x => x.Class, "custom-field"));
// Assert
var wrapper = cut.Find(".sb-form-field");
Assert.Contains("custom-field", wrapper.ClassList);
}
[Fact]
public void AppliesStyleParameter()
{
// Arrange & Act
var cut = RenderFormField(p => p.Add(x => x.Style, "margin: 8px;"));
// Assert
var wrapper = cut.Find(".sb-form-field");
Assert.Contains("margin: 8px", wrapper.GetAttribute("style"));
}
[Fact]
public void AppliesAdditionalAttributes()
{
// Arrange & Act
var cut = RenderFormField(p => p.Add(x => x.AdditionalAttributes, new Dictionary<string, object>
{
{ "data-testid", "form-field" },
{ "aria-describedby", "field-desc" }
}));
// Assert
var wrapper = cut.Find(".sb-form-field");
Assert.Equal("form-field", wrapper.GetAttribute("data-testid"));
Assert.Equal("field-desc", wrapper.GetAttribute("aria-describedby"));
}
[Fact]
public void HelperAndErrorIdsUseInputId()
{
// Arrange & Act
var cut = RenderFormField(p => p
.Add(x => x.InputId, "my-input")
.Add(x => x.HelperText, "Helper")
.Add(x => x.ErrorText, "Error"));
// Assert - ErrorText overrides HelperText display, but both ids should be set
var error = cut.Find(".sb-form-field__error");
Assert.NotNull(error);
Assert.Equal("my-input-error", error.GetAttribute("id"));
// When only HelperText (no ErrorText), helper id should be my-input-helper
var cutHelperOnly = RenderFormField(p => p
.Add(x => x.InputId, "my-input")
.Add(x => x.HelperText, "Helper"));
var helper = cutHelperOnly.Find(".sb-form-field__helper");
Assert.NotNull(helper);
Assert.Equal("my-input-helper", helper.GetAttribute("id"));
}
}