diff --git a/src/Components/Web/src/Forms/InputNumber.cs b/src/Components/Web/src/Forms/InputNumber.cs index fa4d31c0708e..b346b4b39772 100644 --- a/src/Components/Web/src/Forms/InputNumber.cs +++ b/src/Components/Web/src/Forms/InputNumber.cs @@ -53,8 +53,8 @@ protected override void BuildRenderTree(RenderTreeBuilder builder) { builder.OpenElement(0, "input"); builder.AddAttribute(1, "step", _stepAttributeValue); - builder.AddMultipleAttributes(2, AdditionalAttributes); - builder.AddAttribute(3, "type", "number"); + builder.AddAttribute(2, "type", "number"); + builder.AddMultipleAttributes(3, AdditionalAttributes); builder.AddAttributeIfNotNullOrEmpty(4, "name", NameAttributeValue); builder.AddAttributeIfNotNullOrEmpty(5, "class", CssClass); builder.AddAttribute(6, "value", CurrentValueAsString); diff --git a/src/Components/Web/test/Forms/InputNumberTest.cs b/src/Components/Web/test/Forms/InputNumberTest.cs index 793ce20af473..12a7891b4bb4 100644 --- a/src/Components/Web/test/Forms/InputNumberTest.cs +++ b/src/Components/Web/test/Forms/InputNumberTest.cs @@ -1,10 +1,25 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using Microsoft.AspNetCore.Components.Forms.Mapping; +using Microsoft.AspNetCore.Components.Infrastructure; +using Microsoft.AspNetCore.Components.RenderTree; +using Microsoft.AspNetCore.Components.Test.Helpers; +using Microsoft.Extensions.DependencyInjection; + namespace Microsoft.AspNetCore.Components.Forms; public class InputNumberTest { + private readonly TestRenderer _testRenderer; + + public InputNumberTest() + { + var services = new ServiceCollection(); + services.AddLogging(); + _testRenderer = new TestRenderer(services.BuildServiceProvider()); + } + [Fact] public async Task ValidationErrorUsesDisplayAttributeName() { @@ -49,6 +64,43 @@ public async Task InputElementIsAssignedSuccessfully() Assert.NotNull(inputSelectComponent.Element); } + [Fact] + public async Task UserDefinedTypeAttributeOverridesDefault() + { + // Arrange + var model = new TestModel(); + var hostComponent = new TestInputHostComponent + { + EditContext = new EditContext(model), + ValueExpression = () => model.SomeNumber, + AdditionalAttributes = new Dictionary + { + { "type", "range" } // User-defined 'type' attribute to override default + } + }; + + // Act + var componentId = await RenderAndGetTestInputNumberComponentIdAsync(hostComponent); + + // Retrieve the render tree frames and extract attributes using helper methods + var frames = _testRenderer.GetCurrentRenderTreeFrames(componentId); + + var typeAttributeFrame = frames.Array.Single(frame => + frame.FrameType == RenderTreeFrameType.Attribute && + frame.AttributeName == "type"); + + // Assert + Assert.Equal("range", typeAttributeFrame.AttributeValue); + } + + private async Task RenderAndGetTestInputNumberComponentIdAsync(TestInputHostComponent hostComponent) + { + var hostComponentId = _testRenderer.AssignRootComponentId(hostComponent); + await _testRenderer.RenderRootComponentAsync(hostComponentId); + var batch = _testRenderer.Batches.Single(); + return batch.GetComponentFrames().Single().ComponentId; + } + private class TestModel { public int SomeNumber { get; set; }