Skip to content

Component does not re-render if InputFile control included in Razor markup #314

@mrakestraw-bbins

Description

@mrakestraw-bbins

Describe the bug

Per the razor component below, simply add an InputFile tag to your markup and Bunit will not be able to re-render the component upon state change. Sometimes the state will be updated and sometimes not, but never is the markup updated so that you can find markup elements in the else condition of the page.

Note that the input tag works fine.

For reference: Microsoft.AspnetCore.Components.Forms.InputFile

Also, occasionally, I saw a Bunit recursive render stack overflow, but that seemed to be caused by the await LoadForecasts(); in the OnInitializedAsync method. If I see that happen again, I'll try to recreate and open a different bug report.

Example:
Testing this component: WeatherDisplay.razor

@if (Forecasts == null)
{
    <p id="LoadingMessage"><em>Loading...</em></p>
}
else
{
    <InputFile Id="sampleInputFileIdbad" />
    <input type="file" id="sampleInputFileId" />
    <table id="forecasttable" class="table">
        <thead>
            <tr>
                <th>Date</th>
                <th>Temp. (C)</th>
                <th>Temp. (F)</th>
                <th>Summary</th>
            </tr>
        </thead>
        <tbody>
            @foreach (var forecast in Forecasts)
            {
                <tr>
                    <td>@forecast.Date.ToShortDateString()</td>
                    <td>@forecast.TemperatureC</td>
                    <td>@forecast.TemperatureF</td>
                    <td>@forecast.Summary</td>
                </tr>
            }
        </tbody>
    </table>
}


@code {

    [Inject]
    public HttpClient Http { get; set; }

    public List<WeatherForecast> Forecasts;

    protected override async Task OnInitializedAsync()
    {
        await LoadForecasts();
    }

    public async Task LoadForecasts()
    {
        var results = await Http.GetFromJsonAsync<WeatherForecast[]>("sample-data/weather.json");
        Forecasts = results.ToList();
    }

    public class WeatherForecast
    {
        public DateTime Date { get; set; }
        public int TemperatureC { get; set; }
        public string Summary { get; set; }
        public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
    }
}

With this test:

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using BBINS.Shared;
using Bunit;
using RichardSzalay.MockHttp;
using Xunit;

namespace Client.Test
{
    public class WeatherDisplayTests : TestContext
    {
        public WeatherDisplayTests()
        {
            var mock = Services.AddMockHttpClient();
            mock.When("/sample-data/weather.json").RespondJson(new List<WeatherDisplay.WeatherForecast> {
                new()
                {
                    Date = new DateTime(1990, 12, 31),
                    Summary = "Freezing",
                    TemperatureC = 1
                },
                new()
                {
                    Date = new DateTime(2001, 12, 31),
                    Summary = "Freezing",
                    TemperatureC = 2
                }
            });
        }

        [Fact]
        public void WeatherDisplayInitializeTest()
        {
            var cut = RenderComponent<WeatherDisplay>();

            // Is this a race condition?
            Assert.Equal("Loading...", cut.Find("p#LoadingMessage").TextContent);
        }

        [Fact]
        public void WeatherDisplayInitializeTest2()
        {
            var cut = RenderComponent<WeatherDisplay>();
            cut.WaitForState(() => cut.Instance.Forecasts != null);

            // Will not find the table if InputFile included in Razor
            cut.WaitForAssertion(() => cut.Find("#forecasttable"));
        }
    }
}

Results in this output:

C:\src\BBINS-bUnit>dotnet test
  Determining projects to restore...
  All projects are up-to-date for restore.
  BBINS-bUnit -> C:\src\BBINS-bUnit\BBINS-bUnit\bin\Debug\net5.0\BBINS.dll
  BBINS-bUnit (Blazor output) -> C:\src\BBINS-bUnit\BBINS-bUnit\bin\Debug\net5.0\wwwroot
  Client.Test -> C:\src\BBINS-bUnit\Client.Test\bin\Debug\net5.0\Client.Test.dll
Test run for C:\src\BBINS-bUnit\Client.Test\bin\Debug\net5.0\Client.Test.dll (.NETCoreApp,Version=v5.0)
Microsoft (R) Test Execution Command Line Tool Version 16.8.3
Copyright (c) Microsoft Corporation.  All rights reserved.

Starting test execution, please wait...
A total of 1 test files matched the specified pattern.
[xUnit.net 00:00:02.43]     Client.Test.WeatherDisplayTests.WeatherDisplayInitializeTest2 [FAIL]
  Failed Client.Test.WeatherDisplayTests.WeatherDisplayInitializeTest2 [1 s]
  Error Message:
   Bunit.Extensions.WaitForHelpers.WaitForFailedException : The state predicate did not pass before the timeout period passed.
  Stack Trace:
     at Bunit.RenderedFragmentWaitForHelperExtensions.WaitForState(IRenderedFragmentBase renderedFragment, Func`1 statePredicate, Nullable`1 timeout) in /_/src/bunit.core/Extensions/WaitForHelpers/RenderedFragmentWaitForHelperExtensions.cs:line 31
   at Client.Test.WeatherDisplayTests.WeatherDisplayInitializeTest2() in C:\src\BBINS-bUnit\Client.Test\WeatherDisplayTests.cs:line 45

Failed!  - Failed:     1, Passed:     1, Skipped:     0, Total:     2, Duration: 1 s - Client.Test.dll (net5.0)

Expected behavior:
If I comment out the <InputFile /> tag, I get:

C:\src\BBINS-bUnit>dotnet test
  Determining projects to restore...
  All projects are up-to-date for restore.
  BBINS-bUnit -> C:\src\BBINS-bUnit\BBINS-bUnit\bin\Debug\net5.0\BBINS.dll
  BBINS-bUnit (Blazor output) -> C:\src\BBINS-bUnit\BBINS-bUnit\bin\Debug\net5.0\wwwroot
  Client.Test -> C:\src\BBINS-bUnit\Client.Test\bin\Debug\net5.0\Client.Test.dll
Test run for C:\src\BBINS-bUnit\Client.Test\bin\Debug\net5.0\Client.Test.dll (.NETCoreApp,Version=v5.0)
Microsoft (R) Test Execution Command Line Tool Version 16.8.3
Copyright (c) Microsoft Corporation.  All rights reserved.

Starting test execution, please wait...
A total of 1 test files matched the specified pattern.

Passed!  - Failed:     0, Passed:     2, Skipped:     0, Total:     2, Duration: 523 ms - Client.Test.dll (net5.0)

Version info: Test Project

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>net5.0</TargetFramework>

    <IsPackable>false</IsPackable>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="bunit.web" Version="1.0.0-preview-01" />
    <PackageReference Include="bunit.xunit" Version="1.0.0-preview-01" />
    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.1" />
    <PackageReference Include="RichardSzalay.MockHttp" Version="6.0.0" />
    <PackageReference Include="xunit" Version="2.4.1" />
    <PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
      <PrivateAssets>all</PrivateAssets>
    </PackageReference>
    <PackageReference Include="coverlet.collector" Version="1.3.0">
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
      <PrivateAssets>all</PrivateAssets>
    </PackageReference>
  </ItemGroup>

  <ItemGroup>
    <ProjectReference Include="..\BBINS-bUnit\BBINS-bUnit.csproj" />
  </ItemGroup>

</Project>

Version Info: Blazor WASM project

<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">

  <PropertyGroup>
    <TargetFramework>net5.0</TargetFramework>
    <AssemblyName>BBINS</AssemblyName>
    <RootNamespace>BBINS</RootNamespace>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="5.0.2" />
    <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="5.0.2" PrivateAssets="all" />
    <PackageReference Include="System.Net.Http.Json" Version="5.0.0" />
  </ItemGroup>

</Project>
C:\src\BBINS-bUnit>dotnet --info
.NET SDK (reflecting any global.json):
 Version:   5.0.102
 Commit:    71365b4d42

Runtime Environment:
 OS Name:     Windows
 OS Version:  10.0.18363
 OS Platform: Windows
 RID:         win10-x64
 Base Path:   C:\Program Files\dotnet\sdk\5.0.102\

Host (useful for support):
  Version: 5.0.2
  Commit:  cb5f173b96

.NET SDKs installed:
  3.1.405 [C:\Program Files\dotnet\sdk]
  5.0.101 [C:\Program Files\dotnet\sdk]
  5.0.102 [C:\Program Files\dotnet\sdk]

.NET runtimes installed:
  Microsoft.AspNetCore.All 2.1.24 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.App 2.1.24 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 3.1.10 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 3.1.11 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 5.0.1 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 5.0.2 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 2.1.24 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 3.1.10 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 3.1.11 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 5.0.1 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 5.0.2 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.WindowsDesktop.App 3.1.10 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 3.1.11 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 5.0.1 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 5.0.2 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]

Metadata

Metadata

Assignees

No one assigned

    Labels

    help wantedExtra attention is neededinvestigateThis issue require further investigation before closing.questionFurther information is requested

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions