Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Activity
  • Feb 28 14:49
    egil opened #336
  • Feb 24 20:41
    egil opened #333
  • Feb 23 09:31
    egil closed #303
  • Feb 22 10:11
    egil edited #329
  • Feb 22 10:07
    egil edited #329
  • Feb 22 09:34
    codecov[bot] commented #328
  • Feb 22 09:34
    codecov[bot] commented #328
  • Feb 22 08:51
    codecov[bot] commented #328
  • Feb 22 08:21
    codecov[bot] commented #328
  • Feb 21 14:00
    codecov[bot] commented #328
  • Feb 21 14:00
    egil synchronize #328
  • Feb 21 13:58
    codecov[bot] commented #328
  • Feb 21 13:56
    codecov[bot] commented #328
  • Feb 21 13:56
    egil synchronize #328
  • Feb 21 11:23
    codecov[bot] commented #328
  • Feb 21 11:23
    egil synchronize #328
  • Feb 21 09:23
    egil synchronize #303
  • Feb 21 09:20
    egil commented #303
  • Feb 21 09:18
    egil synchronize #303
  • Feb 21 09:18
    egil synchronize #303
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
Brett McDonald
@bfmsoft
If I want to test a component that has phases. It returns state one and then after it finishes loading returns another state. How can I tell the CUT to rerender after I change the MOQ so it will return the second state? Basically, I want to do the first MarkupMatches(Frag1), change the MOQ so will return the second state, then "somehow tell component to rerender" then do Second MarkupMatches(Frag2)?
Egil Hansen
@egil
@bfmsoft doesnt you changing the Moq somehow causes the component to render automatically?
Otherwise, how does it work in a real app?
Anyway, to answer your question, you can always call cut.Render() or cut.SetParametersAndRender(...) if you need to pass new parameters.
Brett McDonald
@bfmsoft
@egil problem is I don't see Render or SetParametersAndRender offered on "cut" it is type IRedenderedFragment. I am using Razer style tests and fixture.GetComponentUnderTest. I'll reread the article you listed.
Egil Hansen
@egil
ahh you need to use GetComponentUnderTest<TComponent>()
That will return a IRenderedComponent<TComponent>
Marc Chu
@demonsweatlive
Running into some behavior I don't understand. I have a Page component. The Page has a Form component. The Form has controls on it. I am asserting on the contents of the form. I have one particular test where the contents of the form controls are not what I'm expecting. When I examine the markup of the Page, the contents are exactly what I expect to see. But when I examine the contents of the form IRenderFragment, retrieved with _RenderedPage.FindComponent<Form>(), they are different, containing values that were set previously in the test but that were subsequently cleared out.
What could be going on here? Is there some need to refresh something? Is there some race condition?
Egil Hansen
@egil
Hi @demonsweatlive, not sure without seeing any code, but it could be a race condition. For that, you might need this: https://bunit.egilhansen.com/docs/verification/async-assertion.html
Marc Chu
@demonsweatlive
This is what confuses me:
Marc Chu
@demonsweatlive
   IRenderedComponent<Page> _RenderedPage = context.RenderComponent<Page>(); // initialised early in test
//in assertion phase
var markup = _RenderedPage.Markup; //<-------- This markup has exactly what I expect for the Form component.
var form = _RenderedPage.FindComponent<Form>();   
var formMarkup = form.Markup; //  <---------- This markup is different. It has outdated values
How can they be different?
Egil Hansen
@egil
Not sure. Do you do anything between reading the markup from RenderedPage and Form?
Marc Chu
@demonsweatlive
Nothing. Everything in the Act phase is done by this point.
Egil Hansen
@egil
so the markup in form is different from RenderedPage.Find("form"). E.g. you can do RenderedPage.FindComponent<Form>().MarkupMatches(RenderedPage.Find("form")) assuming there is only one form element on the page
I have to run pick up the kids, but if you can create a minimal example that reproduces this issue and share it in the github repo through an issue, that would be great.
From what you are telling me it should not be different.
Marc Chu
@demonsweatlive
I'm not sure I'll be able to do that...I have a few hundred tests running through the same code, and 2 dozen or so in the same Specflow feature (testing this particular page of my app), and they all pass successfully. Hence, my confusion.
Very difficult to understand what it is about this particular test that could be causing this.
Peter Morris
@mrpmorris
OMG Trump is an idiot
The governor of (Texas?) told him that he expected to lose his seat but was re-elected, and Trump is more popular than him so there is no way Trump could have lost
This guy ran a country?
Egil Hansen
@egil
@demonsweatlive can you share the code with me? Could just be a private repo that you grant me temp access to on github. If its just the one test failing I can debug it and figure it out.
@mrpmorris its impressive indeed. But thankfully he needs to convince the courts, and so far that has not been going great.
Marc Chu
@demonsweatlive
@egil I'm not sure it's doable, given the massive size of the code base, and paring it down to bare essentials doesn't feel like it would be worth the effort, at this point. I do recall running into an error reminiscent of this, so I'm just going to plow forward and hope I can figure it out eventually. If not, then I'll circle back around. I was just hoping there was something obvious that I was missing. There's a chance that it could have to do with async state, so I'll focus on that.
Egil Hansen
@egil
@demonsweatlive thats fair. Just to recap, this is the basis of what you are seeing:
  1. Render component Foo which has subcomponent Bar.
  2. Do something to cause component Bar to rerender and have changes in its markup
  3. Be able to view the markup changes of component Bar through parent component Foo.Markup AND NOT be able to see the changes in Bar.Markup.
Does that sum it up?
If so, I am very curious to hear what learn what you are doing in step 2.
Marc Chu
@demonsweatlive
image.png
@egil The entire page is a component, with subcomponents of grid and form. If I edit something on the form, then click on different grid item, I'm prompted by a modal as to whether I want to discard the changes, save the changes, or cancel switching to the new user.
My test is doing that, choosing to "Discard" the changes, then clicking on another grid item (which does a server fetch), and then back to the original grid item (another fetch) in order to make sure that nothing was modified.
Marc Chu
@demonsweatlive
And yes, you describe it correctly. The Page component gives every indication that everything is as expected.
However, I'm asserting on the Form sub-component, and there, the values are different. There items that I entered previously that should have been discarded. As though nothing in that sub-component changes after some point.
This happens whether I have a reference to the rendered Form saved from the beginning of the test, which works everywhere else and for every test; or whether I FindComponent<Form>() from the rendered Page at assert time.
It's as though something is internally caching that form and giving me an older state
Marc Chu
@demonsweatlive
I should also note that this is using v 1.0.0.0-beta-10. I saw that there is a beta 11 now, but after I changed all the ClickAsync() calls to Click(), I had many, many, MANY more breaking tests. So I backed that right out, because I just don't have the energy for that.
Egil Hansen
@egil
@demonsweatlive I removed ClickAsync since it didnt really make a difference if you awaited it or not. So you should be able to do a search and replace.
Marc Chu
@demonsweatlive
@egil Not worried about the API change, easy enough. I mean that after the code changes, many of the tests were now failing.
Egil Hansen
@egil

It's as though something is internally caching that form and giving me an older state

There is a single RenderTree that is updated when a component renders. But what can happen is that your changes are happening asynchronously... put differently, the blazor renderer that is updating the render tree is updating it in a different thread than the one the test is running in, so the changes might be coming, but might not be there yet. The problem you are seeing might be due to beta-10 though. There was some changes to have the render tree updates would update the markup in the components, and you might be seeing a corner case I believe is fixed now.

@egil Not worried about the API change, easy enough. I mean that after the code changes, many of the tests were now failing.

OK. That surprises me. Are you saying tests that use something like await cut.Find("button").ClickAsync() now fails with cut.Find("button").Click()?