Giter Club home page Giter Club logo

bunit-dev / bunit Goto Github PK

View Code? Open in Web Editor NEW
1.1K 25.0 98.0 7.15 MB

bUnit is a testing library for Blazor components that make tests look, feel, and runs like regular unit tests. bUnit makes it easy to render and control a component under test’s life-cycle, pass parameter and inject services into it, trigger event handlers, and verify the rendered markup from the component using a built-in semantic HTML comparer.

Home Page: https://bunit.dev

License: MIT License

C# 99.25% HTML 0.75% CSS 0.01% PowerShell 0.01%
razor-components unit-testing blazor blazor-components xunit nunit mstest component-testing hacktoberfest bunit

bunit's Introduction

GitHub tag Nuget Issues Open

bUnit - a testing library for Blazor components

bUnit is a testing library for Blazor Components. Its goal is to make it easy to write comprehensive, stable unit tests. With bUnit, you can:

  • Setup and define components under tests using C# or Razor syntax
  • Verify outcomes using semantic HTML comparer
  • Interact with and inspect components as well as trigger event handlers
  • Pass parameters, cascading values and inject services into components under test
  • Mock IJSRuntime, Blazor authentication and authorization, and others

bUnit builds on top of existing unit testing frameworks such as xUnit, NUnit, and MSTest, which run the Blazor component tests in just the same way as any normal unit test. bUnit runs a test in milliseconds, compared to browser-based UI tests which usually take seconds to run.

Go to bUnit.dev to learn more.

NuGet Downloads

bUnit is available on NuGet in various incarnations. Most should just pick the bUnit package:

Name Description NuGet Download Link
bUnit Includes the bUnit.core and bUnit.web packages. Nuget
bUnit.core Core library that enables rendering a Blazor component in a test context. Nuget
bUnit.web Adds support for testing Blazor components for the web. This includes bUnit.core. Nuget
bUnit.template Template, which currently creates xUnit-based bUnit test projects only. Nuget
bUnit.generators Source code generators to minimize code setup in various situations. Nuget
bUnit.web.query bUnit implementation of testing-library.com's query APIs. Nuget

To get started, head to the getting started documentation to learn more.

Sponsors

A huge thank you to the sponsors of my work with bUnit. The higher tier sponsors are:

@Progress-Telerik
Progress Telerik
@syncfusion
Syncfusion
@aws
Amazon Web Services

Contributors

Shout outs and a big thank you to all the contributors to the library, including those that raise issues, provide input to issues, and those who send pull requests. Thank you!

These good people have contributed code or documentation to bUnit:

Code of conduct

This project has adopted the code of conduct defined by the Contributor Covenant to clarify expected behavior in our community. For more information see the .NET Foundation Code of Conduct.

.NET Foundation

This project is supported by the .NET Foundation.

bunit's People

Contributors

bunitbot avatar denisekart avatar dependabot[bot] avatar duracellko avatar edcharbeneau avatar egil avatar grishat avatar hschwichtenberg avatar icnocop avatar jgoday avatar joro550 avatar kasperhesthaven avatar kristofferstrube avatar kurnakovv avatar lewis-allen avatar linkdotnet avatar msynk avatar nemesv avatar pbouillon avatar pharry22 avatar rodolfograve avatar samtrion avatar scottsauber avatar simoncropp avatar siphonophora avatar stefh avatar tdroogers avatar thopdev avatar ventigrande avatar yourilima avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

bunit's Issues

Unable to test navigation to another page that should happen on button click.

Describe the bug
In my test component, i have a button which on click navigates the user to another page/component. When I write a test to verify the navigation, the test fails after btn.Click() event fires.

Example:
Component Under Test:

<button id="xyz" @onclick="@(() => UriHelper.NavigateTo("/reports/today"))/>

Test method:

//Arrange
Services.AddSingleton(new Mock<NavigationManager>().Object);
_cut = RenderComponent<Abc>();	
//Act
var btn = _cut.Find("#xyz");
btn.Click();

Throws out exception with message "Navigation Manager Proxy has not been initialized".

Results in this output:
image
image

Expected behavior:
The navigation happens to the specified page and i should be able to assert it from my test method.

Version info:

  • Library version:
  • .NET Core/Blazor version:

Additional context:
If the navigation happens as expected, how do I write assert statements to verify the same? The navigation renders a whole different component, so the _cut will become invalid.

Make DOM nodes retrieve in a test reusable across render tree updates

Currently, when DOM elements or nodes is retrieved from the IRenderedFragment, e.g. var elm = cut.Find(), it is only valid until the render tree is changed and a new DOM tree is created. E.g.

var cut = RenderComponent<Counter>();
var btn = cut.Find("button");

btn.Click();

Assert.Equal("Current count: 1", cut.Find("p").TextContent);

btn.Click();

// This fails since the second btn.Click() points to a button that had been replaced after the first click.
Assert.Equal("Current count: 2", cut.Find("p").TextContent);

This might confuse people, and it also do not allow us to query for the DOM nodes a test needs in the tests arrange step and reuse.

Describe the solution you'd like
With the current render logic where the DOM tree is recreated after ever render tree change, one solution could be to create wrapper types for all the DOM nodes that AngleSharp has. It is possible to do in a clean way because all are exposed in AngleSharp add interfaces.

Then each wrapper will know:

  • have a way to be notified if the node it is wrapping needs to be replaced/has become stale
  • it will have a Func passed to it when constructed that allows it to recreate the DOM node (from the IRenderedFragment or another wrapped DOM node)
  • it will throw an error if the wrapped DOM node is no longer in the DOM tree after a render tree update
  • for internal use it should provide a way to access the wrapped DOM node to not slow down DOM diffing
  • it should wrap any DOM nodes returned to a caller of methods/properties on it the returns DOM nodes, e.g. FirstChild

Add a component parameter builder or make param helpers more easily accessible

Related to #5, where support for new test libs is planned, it will probably be a good idea to make it easier for users wanting to pass parameters to CUTs to do so without having to inherit from a base class in their tests, e.g. following the pattern of:

public void TestMethod()
{
    using var ctx = new TestContext();
    var params = new ComponentParameterBuilder(this) // 'this' might be needed to capture the execution context for callback parameters.
        .With("name", value)
        .WithCallback("name", () => {})
        .WithCascadingValue(obj)
        .WithChildContent("<p>hello world</p>")
        // ... etc
        .Build(); // Build could be done implicitly through a implicit conversion to ComponentParameter[]
    ctx.RenderComponent(params);
}

AngleSharpRenderer - a way to update DOM nodes when render tree changes during a test

Right now, every time a new render tree is created during a test, the markup and DOM nodes are recreated. That causes some issues (#46, #47) and probably has an impact on performance.

A better solution is to do what Blazor does -- i.e. update the initially created DOM tree using the RenderBatch created after each render. Since AngleSharp more or less is a complete W3C implementation of the DOM api, it should be possible to port the Typescript logic from Blazor to C#, so wheels do not have to be reinvented.

Assert helper suggestions

Hi all

Let us use this issue for tracking suggestions for additional assertion helpers that should go into the 1.0.0 release.

Add a comment below with the suggestion you need and we can all vote for it.

Add "Blazor" to project description and readme

I had a hard time finding this project when searching for it because I searched for things like "Blazor test framework", but "Blazor" doesn't appear in the project description or readme. I was recommend updating the project description and readme to mention "Blazor" somewhere, just so it's easier to find.

Question on Handling ValidSubmit in ChildContent,

Child Component contains:

. . . . Save

Test Contains:

        var cut = RenderComponent<TelerikRootComponent>(
            ChildContent<Lookup>(),
            CascadingValue("GridData", lookupEntities),
            CascadingValue("LookupName", "Item")
            );

        cut.Find("#Add_button").Click();
        cut.Find("#Name_textbox").InnerHtml = name;
        cut.Find("#Description_textarea").InnerHtml = description;
        cut.Find("#Save_button").Click(); <-- Wants an onclick 

The click event should fire the OnValidSubmit.

I am unsure how to get this to work.

Any help would be appreciated.

Thanks,

Jeff

Make event dispatchers emulate browser behaviour where possible

Is your feature request related to a problem? Please describe.
If a user clicks a submit button during testing which is part of a form, with the intent of submitting the form, the form will not be submitted, and it will might be obvious to the user why (#50).

It could also be a Click() on a <input type="checkbox"> element, with the intention of changing the checked state. The state of the checkbox could be using <input type="checkbox" @bind="handleClicks" />, where handleClicks is just a boolean field, e.g. bool handleClicks = true;.

This results in Blazor adding an "onchange" event to the element, and not a "onclick" event, which causes the test to fail, if the user tries to checkbox.Click().

Describe the solution you'd like
In the event dispatch helpers we have access to the element on which an event is being triggered.

This allows us to see if e.g. a submit button is inside a form and redirect a Click to it, or if a input checkbox has an onchange event handler and redirect a Click to Change(..).

Describe alternatives you've considered
Throw a custom exception that explain to the user that it e.g. probably want to submit the form instead.

Additional context
This behavior should only be for emulate how a browser does it.

Waiting operations and multi-threading

This issue tracks discussion about architectural decisions about asynchronous operations and multi-threading.

Current status
This discussion was initiated by identification of following points during PR #27:

  1. Methods WaitForNextRender and DispatchAndAssertNoSynchronousErrors are blocking and not returning a Task object.
  2. Test code run in 2 threads. Test code starts in thread managed by test framework. Then every operation (e.g. rendering, mocked JS events) runs in Razor Dispatcher thread.

Open question 1
Shall in general waiting operations like WaitForNextRender and DispatchAndAssertNoSynchronousErrors be blocking? Or should they return Task object that can be awaited?

Open question 2
Should whole test run in synchronization context of Razor Dispatcher? Or is it desired to run tests in 2 synchronization contexts?

If no IJsRuntime has been added to Services at render time, add a dummy that will throw if requested

To make it easier for users to discover the JsRuntime Mock and how/when they need it, I think it would be a great solution to register a dummy IJsRuntime just before the service collection gets turned into a service provider. That dummy should simply throw an exception if every instantiated with a descriptive message to the user about providing i IJsRuntime with links to JsRuntimeMock documentation.

Change ShouldBe to MarkupMatches

The ShouldBe name is too generic and it is not clear with cut.ShouldBe(...) what is actually being verified, i.e. rendered markup. The best alternative ive come up with is cut.MarkupMatches(...) which more clearly signals that it is the markup of cut that should match something else.

Make event dispatchers also have side effect on elements they are triggered on

Is your feature request related to a problem? Please describe.
All the event dispatch helpers current just trigger the event handler attached to the event on the DOM element. They do not have any side effects on the elements they are triggered on.

E.g. if it is an <input type="text"/> element, triggering KeyPress("foo") only triggers the @onkeypress="..." binding, but does not set the Value attribute on the input element. That might not be what we expect to happen.

The challenge with this is that the nodes are being recreated whenever a components render tree has changes, thus we introduce the side effects manually when a event is triggered.

It does look as if we could raise events via the AngleSharp DOM elements (https://anglesharp.github.io/docs/Examples.html#events-in-javascript-and-c), and even hook in our c# event bindings if we wish, but the nodes would still be recreated.

Describe the solution you'd like
With the current "TestRenderer -> Markup -> DOM nodes" render pipeline, I do not see a good solution that would work as expected in all cases. I am tempted to just accept this as a limitation for now.

Long term, the ideal solution would be to use the RenderBatch produced by the Renderer whenever there are changes, and apply those to an AngleSharp DOM tree, similar to how Blazor modifies the DOM tree in the browser using JavaScript. That would likely involved porting the typescript logic to c# and the AngleSharp DOM api. Fortunately, the AngleSharp DOM api is very compatible with the W3Cs, so it's not an impossible task.

Create custom xUnit test runner/discoverer

There are to problems with using the default runners/discoverers:

  1. Currently are all <Fact/> tests inside the same .razor file, which runs the default expected output html test, listed as one test in the test runner. A custom test discovere for xUnit seems like the right approach to get the correct Facts reported to the test runner. It should also use the DisplayName attribute when finding tests.

  2. If multiple xUnit tests exists in the same .razor file (declared via [Fact] attributes), the entire .razor component is re-rendered each time a test is executed, and a new renderer is instantiated each time. With a custom test runner we should be able to reuse the same renderer and then cache the output from the initial render. An alternative is to figure out how to only render some parts of a .razor file at the time.

There are some samples in the xunit repo that shows how to create both a custom discoverer and test runner: https://github.com/xunit/samples.xunit

The render handle is not yet assigned.

I am getting an exception when trying to render my component.

Any directional help would be appreciated.

Here is my test:

[Fact(DisplayName = "Test to see the Lookup Renders Properly - Select Grid Item")]
        public void LookupRendersCorrectlySelectGridItem()
        {
            // Arrange
            var active = true;
            var id = 1;
            var description = "Item 1";
            var name = "Item1";
            var lookupEntities = new List<LookupViewModel>() { new LookupViewModel() { Active = active, Id = id, Description = description, Name = name } };
            var tipClient = new Mock<ITipClient>();
            tipClient.Setup(x => x.GetJsonAsync<List<LookupViewModel>>(It.IsAny<string>())).Returns(Task.FromResult(lookupEntities));

            Services.AddSingleton<ITipClient>(tipClient.Object);
            Services.AddMockJsRuntime();
            Services.AddTelerikBlazor();

            var root = new TelerikRootComponent();

            // Act
            var cut = RenderComponent<Lookup>(
                CascadingValue(root),
                CascadingValue("GridData", lookupEntities)
                );

            // Assert
            Assert.NotNull(cut);
        }

Mocking components in render tree

Hard to arrange tests
The issue #52 and #38 is an example of a test that is hard to "arrange" because a sub-component of the component under test, employs a lot of JSInterop to do its work. It could also be a 3rd party component that is used in the component under test, that has a dependency on a service, that the test would have to provide a mock of to get a test to work as expected.

Describe the solution you'd like
It would be nice to be able to mock out the sub-component that has external dependencies that is not important to the test. That would make the test much easier to arrange, being able to mock or replace a sub-component in a render tree.

It is not clear if it will be possible to mock or replace a component. A few problems I see:

  1. Components are normally regular (partial) classes. Those are not easy to mock by tools such as Moq.
  2. To properly mock a component, it would have to be replaced/mocked before the component is instantiated by the Renderer, through a RenderTreeBuilder.OpenComponent(). It is possible that the same trick we have discussed in #17 could be repurposed, iff it is possible to create a mocked instance of the component.

Additional context
This could be related to #17.

Change GetNodes and GetMarkup to properties

The IRenderFragment GetMarkup() and GetNodes() are now only recomputed after a render, thus it makes sense to make the API a little cleaner by changing them into properties called Markup and Nodes.

Beta 5 - Services does not expose IServiceCollection

While the TestServiceProvider now inherits the IServiceCollection Interface, the IServiceCollection interface is not exposed to the client, leaving the client with no way to register services.

Please expose a property that will return the IServiceCollection.

var modal = new Mock();
Services.AddService(modal.Object); <--- No longer valid.

In addition if you expose IServiceCollection:

services.AddTelerikBlazor(); will be exposed <--- Needed for TelerikGrid

AddScoped
AddSingleton

etc

Consider HTML-alternative to XMLDiff

XMLDiff is great, but it requires HTML to be in valid XML/XHTML format. It would be great if we could find an alternative that is more compatible with HTML5.

ElementReference only added to rendered markup during first render

After further investigation, it looks as if this issue is not solvable as the RenderTreeDiffBuilder doesn't include the element reference id during later renders.

The logic in Blazor assumes that the DOM tree is not replaced at each render, but simply updated.

This will probably be easily solvable with #48.

Remove MockHttp logic from library

I have decided to completely remove MockHttp support in the library, and instead add a page on the Wiki describing how to do this. I do not want a dependency on a particular 3. party mocking library, just as we do not include Moq or similar.

The simple test example that adds http mocking to the TestServiceProvider looks like this:

        public async Task AddMockToLibraryExample()
        {
            using var provider = new TestServiceProvider();
            provider.AddSingleton<MockHttpMessageHandler>();
            provider.AddSingleton<HttpMessageHandler>(srv => srv.GetRequiredService<MockHttpMessageHandler>());
            provider.AddTransient<HttpClient>(srv => new HttpClient(srv.GetRequiredService<HttpMessageHandler>()));
            var mockHttp = provider.GetService<MockHttpMessageHandler>();
            var httpClient = provider.GetService<HttpClient>();

            mockHttp.When("http://localhost/api/user/*")
                .Respond("application/json", "{'name' : 'Test McGee'}"); // Respond with JSON

            var response = await httpClient.GetAsync("http://localhost/api/user/1234");
            var json = await response.Content.ReadAsStringAsync();
            
            json.ShouldBe("{'name' : 'Test McGee'}");
        }

Docs update

I would have added this myself, but just realized how much of a pain in the ass GitHub wiki is.

To create a project for testing you Blazor components, first install the Razor Components Testing Project Template from NuGet, using this command:

dotnet new --install Razor.Components.Testing.Library.Template::1.0.0-beta-5.1

Then to create a new project, use the following command:

dotnet new razortest -o <NAME OF TEST PROJECT>

where -o is used to name the test project.

Optional CLI steps

Link the test project to your solution

dotnet sln <NAME OF PROJECT>.sln add <NAME OF TEST PROJECT>

Add a reference your components to be tested in your test project.

dotnet add <NAME OF COMPONENT PROJECT>.csproj reference <NAME OF TEST PROJECT>.csproj

Enable snapshotting / auto-generating ExpectedHtml

I could be useful to enable snapshotting in the library. That would could help make tests even easier to create in a "test-after" scenario, and will make it easier to do automated regression testing. How it should work needs to be designed, but these are my initial thought:

  • <Fact/> gets an parameter EnableSnapshotting, and when set to true, it will automatically generate the <ExpectedHtml> section inside the <Fact/> component, if its doesn't exist already.
  • <ExpectedHtml> could get an an parameter that indicates when it was generated (commit id, date time?)

Two challenges with this:

  1. How to get the location of the Test.razor file. This problem seems very environment dependent, e.g. the .razor files might be in different locations depending on the environment (local dev computer, build server, etc.). We need a good strategy here!
  2. Parse and replace the proper sections of the Test.razor. This part doesn't seem hard, using some search and replace for the element.

This is originally an feature request from @chanan.

Make on* HTML event callback actions available in tests

To make it possible to easily test logic related to @on*="callback" bindings in a component under test, e.g. `@onclick' events, the framework should make any event callbacks bound on the component under test (or sub components), after a render. That should enable a custom unit test can trigger them manually.

My current idea is to create an adapter around the default RenderTreeBuilder classs and pass that to the rendering logic. The adapter will intercept calls to AddAttribute<T>(int sequence, string name, EventCallback<T> value) and OpenComponent<TComponent>(int sequence)/CloseComponent() to keep track of string name, EventCallback<T> value pairs associated with each component. Then a unit test can simply call the appropriate event callback in its "act" step.

Looking for how to create unit test with c# when the component creates a canvas (BECanvasComponent)

Hi,
I encounter an issue when I tried to create a unit test for a component that creating a canvas. Unit Test failed with this message.

Message:
Test method TestCanvas threw exception:
System.AggregateException: One or more errors occurred. (Object reference not set to an instance of an object.) ---> System.NullReferenceException: Object reference not set to an instance of an object.
IndexComponent.OnAfterRenderAsync(Boolean firstRender) line 24

This is the line that causes an error in Index.razor.cs.

24.     Console.WriteLine("width={0}.", m.Width.ToString());

Basically, I can't create a JS mock for Blazor.Extensions.Canvas.Canvas2D. Following are the code.

In Index.razor

@page "/Index"
@inherits IndexComponent
<BECanvas Width="800" Height="800" @ref="_canvasReference"></BECanvas>

In Index.razor.cs

using Blazor.Extensions.Canvas.Canvas2D;
using Blazor.Extensions;
public class IndexComponent : ComponentBase
{
    protected BECanvasComponent _canvasReference;
    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
       Canvas2DContext context = await _canvasReference.CreateCanvas2DAsync();
       var m = await context.MeasureTextAsync("Hello Blazor");
       Console.WriteLine("width={0}.", m.Width.ToString());  // Line 24 that causes the error which m returns null in this case.
    }
}

In Test.cs

[TestMethod]
public async Task TestCanvas()
{
    var jsMock = Services.AddMockJsRuntime(JsRuntimeMockMode.Loose);
    var cut = RenderComponent<Index>();
}

Please help.

Trouble running tests

Hi Egil,

I installed the P9 version and trying to test BlazorStyled. I created a test:

<Fact DisplayName="red paragraph">
    <TestSetup>
        <ServerSideStyled />
        <Styled>
            p {
                color: red;
            }
        </Styled>
    </TestSetup>
    <ExpectedHtml>
        <div class="alert fade show" role="alert"></div>
    </ExpectedHtml>
</Fact>

Which should obviously fail. I have the _Imports.razor set the same as the sample. When I run it from dotnet test I get the following:

Test run for C:\Users\cbraunstein\source\repos\BlazorStyled\src\BlazorStyled.SnapshotTests\bin\Debug\netcoreapp3.0\BlazorStyled.SnapshotTests.dll(.NETCoreApp,Version=v3.0)
Microsoft (R) Test Execution Command Line Tool Version 16.3.0-preview-20190820-01
Copyright (c) Microsoft Corporation.  All rights reserved.

Starting test execution, please wait...

A total of 1 test files matched the specified pattern.
No test is available in C:\Users\cbraunstein\source\repos\BlazorStyled\src\BlazorStyled.SnapshotTests\bin\Debug\netcoreapp3.0\BlazorStyled.SnapshotTests.dll. Make sure that test discoverer & executors are registered and platform & framework version settings are appropriate and try again.

Link to project: https://github.com/chanan/BlazorStyled/tree/testing/src/BlazorStyled.SnapshotTests

Add Blazor end-2-end rendering tests

To get a better test coverage of the many different scenarios Blazor components can be rendered in, add all or as many as makes sense of the end-2-end Selenium tests to the testing libraries test suite -- but convert them from Selenium to use bUnit instead.

Testing components with Telerik Grid throws System.InvalidOperationException

I am testing a component that uses the Telerik UI Blazor grid component. The grid component throws an exception: Message=Cannot provide a value for property 'State' on type 'Telerik.Blazor.Components.TelerikGrid, There is no registered service of type 'Telerik.Blazor.Components.Grid.State.IGridState'.

IGridState is private so it cannot be mocked.

I would like some help on how to work around this issue.

Attached is a sample app I put together to demonstrate the issue I am having.

SampleApp.zip

RenderComponent does not wait for all threads to complete before returning.

Describe the bug or question
When a component under test has async methods, the RenderComponent method does not wait for all threads to complete before returning.

Example:
BlazorApp1.zip

Component under test
FetchData

With this test:

FetchDataRendersCorrectly

Results in this output:
SaveAsync is executed after the test method completes.

Expected behavior:
RenderComponent should wait until all threads have completed before returning control to the test method.

Version info:

  • Beta 5.1
  • .NET Core/Blazor 3.1:

MockJsRuntime should have a SetupVoid() method

To make it easier/more intuitive to mock a InvokeVoidAsync call, the MockJsRuntimeInvocationHandler should have a SetupVoid method in addition to the Setup methods.

This means there should probably also be SetCompleted method in JsRuntimePlannedInvocation, or at least a SetResult without parameters.

Submit on form with Required Field Validations does not call the defined OnValidSubmit method

Describe the bug
If a component used validation as described in ASP.NET Core Blazor forms and validation:
https://docs.microsoft.com/en-us/aspnet/core/blazor/forms-validation?view=aspnetcore-3.1

Submit on the form will not call the method defined in the property OnValidSubmit of the EditForm tag.

Example:
Example app is attached.
TelerikBlazorApp1.zip

Component under test
FetchData

With this test:

Unit test in C# or Razor or Snapshot that fails.
```FetchDataRendersCorrectly

Results in this output:
Save method never called
```text
Message output from running the test.

Expected behavior:
A clear and concise description of what you expected to happen.

I expect if the component passes validation the method defined on OnValidSubmit to be called. The test acts like validation is never passed.

Version info:

  • Library version: Beta - 5.1
  • .NET Core/Blazor version: 3.1

Additional context:
Add any other context about the problem here.

Enable shallow rendering mode

The popular shallow rendering mode in Vue/React/Angular testing frameworks, that only render the component under test directly, and not any sub-components it might be using, could be useful in Blazor testing as well.

The TestRenderer and Htmlizer class might allow this. Needs more investigation.

This has been superseded by #396.

WaitForNextRender or similar should be related to a specific IRenderedFragment

It might be better if WaitForNextRender isnt attached to the Test Context but to the Rendered Component instead. That should enable users to specify that they want to wait until the specified rendered component has rerendered, not just wait for any rendering to occur.

The API would probably also make more sense, e.g.:

cut.WaitForNextRender(...);

Here the waiting is attached to the specific cut.

Setting a child component to be a specific type

So my component (SearchSection) has a typed render fragment as shown below.

[Parameter] public RenderFragment<T> TableDataTemplate {get; set;}

Following the example on the wiki, I have tried to mock out the child content in my test as shown below

var template = "<td></td>"
var cut = RenderComponent<SearchSection<int>>(
                ChildContent(template)
);

This fails with
InvalidOperationException: Object does not have a property matching the name 'ChildContent'.

I've also tried another way which is

var template = "<td></td>"
var child = ChildContent(template).Value;

var cut = RenderComponent<SearchSection<int>>(
                (nameof(SearchSection<int>.TableDataTemplate), child)
);

And the error I got is
Unable to cast object of type 'Microsoft.AspNetCore.Components.RenderFragment' to type 'Microsoft.AspNetCore.Components.RenderFragment'1[System.Int32]'

So my question is, is there a way to make the render fragment a certain type?

Where to go from the POC?

The current iteration makes it fairly easy to test the initially generated HTML, in a fairly stable manner (spacing ignored, order of css classes doesnt matter, etc.).

However, a few shortcomings exists currently:

  • The builder-based syntax for creating components and sub components/fragments works, but ideally we could write the SUT as razor code.
  • Defining the expected output HTML in a string works OK but would be nicer in a file (e.g. .razor) where the editor understands HTML and can provide assistance.
  • Missing a way to trigger various on-events (e.g. onclick) on the created SUT component and verify outcome.
  • Missing a way to update a SUT component after first render and verify outcome.

Idears:
I like the idea of defining component tests in a .razor file, that inherits from a ComponentTestFixture class. ComponentTestFixture would be responsible for having the correct unit testing framework annotations, render the SUT component and grap the expected HTML.

It could also support various steps, where each step matches a step in a components life-cycle (i.e. first render, users interaction, parameter changed, disposed). E.g. something like this:

@inherits ComponentTestFixture

<SUT>
    <Alert color="primary"></Alert>
</SUT>

<ExpectedHtml>
    <div class="alert fade show alert-primary" role="alert"></div>
</ExpectedHtml>

Remove dependency on Shouldly

It's probably better not to have an explicit dependency on Shouldly. Users should be able to pick their own assertion library.

Shouldly style assertion could be put into its own nuget package or just included in a sub-namespace.

Bug: Self closing tags don't work right

Running this test:

<Fact DisplayName="br">
    <TestSetup>
<br/>
    </TestSetup>
    <ExpectedHtml>
<br/>     
</ExpectedHtml>
</Fact>

Fails:

[xUnit.net 00:00:00.71]     Rendered HTML should be the same as expected HTML [FAIL]
  X Rendered HTML should be the same as expected HTML [1ms]
  Error Message:
   Egil.RazorComponents.Testing.RazorComponentRenderResultParseException : An error occurred while trying to parse the render result of the test.
The 'br' start tag on line 3 position 2 does not match the end tag of 'Html'. Line 4, position 7. Result XML:
<RenderResults><RenderResult DisplayName="br">
    <Rendered><Html>
<br>
    </Html></Rendered>
    <Expected><Html>
<br>
</Html></Expected>
</RenderResult></RenderResults>
---- System.Xml.XmlException : The 'br' start tag on line 3 position 2 does not match the end tag of 'Html'. Line 4, position 7.

Suggestion: Provide a way to ignore white space

Provide a way to ignore white space when comparing the strings. for example:

Expected HTML:
<Html>
  <style>
            p {
                color: red;
            }
        </style>
</Html>

Rendered HTML:
<Html>
  <style>
        p{color:red;}
</style>
</Html>

Should be the same if IgnoreWhitespace = true

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.