Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Activity
  • Nov 25 20:50
    egil closed #267
  • Nov 25 20:50
    egil commented #267
  • Nov 25 20:40
    RonSijm commented #267
  • Nov 25 20:06
    egil commented #267
  • Nov 25 19:14
    RonSijm edited #267
  • Nov 25 19:14
    RonSijm opened #267
  • Nov 25 16:41
    egil commented #241
  • Nov 25 16:41
    egil labeled #241
  • Nov 25 16:36
    egil edited #241
  • Nov 25 16:11
    egil closed #240
  • Nov 25 14:12
    egil closed #257
  • Nov 24 23:21
    codecov[bot] commented #257
  • Nov 24 23:18
    codecov[bot] commented #257
  • Nov 24 23:18
    egil synchronize #257
  • Nov 24 23:17
    codecov[bot] commented #257
  • Nov 24 23:16
    egil edited #257
  • Nov 24 23:15
    egil edited #257
  • Nov 24 23:15
    egil edited #257
  • Nov 24 23:15
    codecov[bot] commented #257
  • Nov 24 23:14
    egil synchronize #257
Egil Hansen
@egil
Are you loading data from a real data source in your tests, or are you mocking your data source?
Forex Ray
@forex.ray.v1_gitlab
hello @egil , we are loading the real data from the APIs and it's not a mock. That's why there is time delay in the data load.
Egil Hansen
@egil
Then you can use WaitForState(() => cut.FindAll("css selector for element that should show up").Count > 1)
Forex Ray
@forex.ray.v1_gitlab
ah ok. let me try that. Thanks @egil
Egil Hansen
@egil
Ohh forgot to mention, if you need more than 1 second of wait time, you can change that by passing a second parameter to WaitForState, e.g. WaitForState(() => ...., TimeSpan.FromSeconds(xx))
camelCaseSharp
@camelCaseSharp
I am thinking about using bunit to write BDD style tests, these typically involve writing longer UI scenarios than a TDD style unit test. Is is possible for a single bunit cut to navigate between two routable Blazor components (also known as pages)?
Egil Hansen
@egil
Hi @camelCaseSharp
I think so, but I am not sure I exactly understand what you are trying to do.
bUnit doesnt look at the @page directive in components though, so the navigation step will have to be manual.
That said, there is nothing preventing you from calling var page1 = RenderCompoent<Page1>() and var page2 = RenderComponent<Page2>() in the same test class.
And you can pass in the same state to both components. You can even pre-register a cascading value that both should receive through the TestContext.RenderTree, if that is how you share state.
Egil Hansen
@egil

That said, there is nothing preventing you from calling var page1 = RenderCompoent<Page1>() and var page2 = RenderComponent<Page2>() in the same test class.

Correction, IN THE SAME TEST METHOD. You can call RenderComponent as many times as you want within the same test.

camelCaseSharp
@camelCaseSharp
Thanks for the feedback Egil. I was thinking about creating some BDD business test scenarios such as "When I want to pay out approved insurance claims, I first click on 'Pending Claims' in the application dashboard, then select the first approved claim listed then on the summary claim screen click the 'Issue Payment' button.". In a typical LOB Blazor app that scenario might traverse across 3 top level routable components. I gather from your first response that the Blazor navigation manager and location changed events are not hooked into the scope of a CUT?
Egil Hansen
@egil
not by default
But if you want to use navigation manager, you simply register one through the Services collection
I havent tried writing tests where the default blazor router is included, but that might work. you are certainly the first to ask though :)
camelCaseSharp
@camelCaseSharp
Ok thanks @egil I will start using bunit more simply to begin with then experiment with unit tests that navigate across pages.
Egil Hansen
@egil
I recommend starting with just testing individual components. Thats where bUnit execelles. But I am very interested in learning more about your scenario. Feel free to create a QA in the https://github.com/egil/bUnit/discussions. Its a much better place to share code samples and keep track of a discussion.
camelCaseSharp
@camelCaseSharp
Is it possible to create a bunit test that checks for an expected UI update that should occur in response to a data update applied to a Fluxor state store? In this scenario I assume my Blazor component under test is bound to data in the Fluxor state store created as part of the test.
Egil Hansen
@egil
I dont see a problem with that. The only challange might be that the data arrives asynchronously, and thus you might need to use cut.WaitForAssertion(() => /* assertion goes here */) since the test code runs in one thread and the component and renderer in another, to avoid deadlocks.
How is the Fluxor state store made available to the component?
camelCaseSharp
@camelCaseSharp
According to the Fluxor docs the state store is injected as a private property. Yes I was anticipating the need to use cut.WaitForAssertion after reading your replies 13th Nov to @forex.ray.v1_gitlab and how to handle the delay when a unit test makes a live async remote request for data. Your recent presentation with Microsoft available on YouTube was very helpful particularly that bunit architectural slide, now I can picture where the threads run during a unit test.
Egil Hansen
@egil
great, never got to demo waitforassertion though
but glad it helped
Is it injected with DI or is it a cascading value?
Eitherway, you will want a way to control that in your tests. If you can set the data in the store before your render your component, then its likely that the renderer will render the component synchronously and you wont need to use waitforxxx
control it, as have a way to set data in it.
Anyway, when you get it working, do post a sample in the discussions forum under the show and tell category. Will likely be very useful to others.
camelCaseSharp
@camelCaseSharp
The injection is through DI.
[Inject]
private IState<CounterState> CounterState { get; set; }  https://github.com/mrpmorris/Fluxor/blob/master/Tutorials/02-Blazor/02A-StateActionsReducersTutorial/README.md
Egil Hansen
@egil
Ahh its @mrpmorris thats behind that.
Anyway, it does seem like you can just mock or even better, create fake of IState, and then in your test, write Services.AddSingleton<IState<CounterState>>(new FakeState(....))
Peter Morris
@mrpmorris
Yes, and yes :)
PS: @camelCaseSharp -> https://gitter.im/mrpmorris/fluxor
If you are interested
aschaefer94
@aschaefer94
Hi Egil. I'm writing some tests and running into an issue with context menus. Our solution is using a nuget package (Blazor.ContextMenu v.1.8.0) for context menus in our app. It seems like they may be using the HTML 'oncontextmenu' event rather than the blazor '@oncontextmenu' event, would that make it so that the Element.ContextMenu() call in BUnit can't find the event?
Egil Hansen
@egil
hi @aschaefer94, it sounds as if they are listening to that event through javascript. Since bUnit doesnt run javascript, you cannot trigger their javascript code.
its like they have a c# method that is javascript invocable. If thats the case, you can simply invoke that method yourself.
Egil Hansen
@egil
It looks like they are calling a method in their component called ShowMenu and HideMenu: https://github.com/stavroskasidis/BlazorContextMenu/blob/master/BlazorContextMenu/wwwroot/blazorContextMenu.js#L177
But actually, you might jus be able to get one of these out of the services collection and use that: https://github.com/stavroskasidis/BlazorContextMenu/blob/master/BlazorContextMenu/Services/BlazorContextMenuService.cs#L10
It has hide and show menu methods
aschaefer94
@aschaefer94
That's a good find on the service. It doesn't seem like making the call on the service actually changes my html at this point. Should I be able to call instance methods on their component from my code? It doesn't seem like the ShowMenu and HideMenu methods are publicly available for me to call something like cut.ShowMenu() in my test code.
Egil Hansen
@egil
calling those methods might trigger an async render, which you need to tell your test to wait for. So try adding a cut.WaitForState(() => cut.FindAll("query selector elements you expect").Count > 0)
Otherwise, you can always try to find components in the component tree by using cut.FindComponent<TypeOfComponent>()
Then you can do e.g. var menu = cut.FindComponent<ContextMenu>() and then inspect menu.Instanceto see what options you have on the component.
Egil Hansen
@egil

So some times I really want to kick myself for not thinking of something earlier. This is one of those times. This morning I realized that the inline render fragment syntax in razor has the potential for much better razor based tests.

Have small spike, where this is possible:

@inherits TestComponentBase2
@code
{
    [Fact]
    public void Test1()
    {
        var cut = RenderFragment(@<div>hello world</div>);

        cut.MarkupMatches(@<div>hello world</div>);
    }

    [Fact]
    public void Test2()
    {
        var cut = RenderComponent<Counter>(@<Counter DarkMode="true">
                                            </Counter>);

        Assert.True(cut.Instance.DarkMode);
    }

    [Fact]
    public void Counter_Increments_When_Button_Is_Clicked()
    {
        var cut = RenderFragment(@<Counter DarkMode="true" />);

        cut.Find("button").Click();

        cut.Find("p").MarkupMatches(@<p>Current count: 1</p>);
    }
}

What do you guys think?

Peter Morris
@mrpmorris
That looks very good!
I like it a lot