Replies: 3 comments
-
The safe way to read the rendertree is synchronously during the Do you think you could maybe post a small code snippet that illustrates the interaction between bUnit framework code and the renderer, showing why the bUnit parts can't be triggered by the Thanks! |
Beta Was this translation helpful? Give feedback.
-
@SteveSandersonMS, that's actually how bUnit is doing it currently, but only for re-renders and not for initial renders. And it was the initial render scenario that is causing a subtle bug once in a while (bug 189) that prompted me to revisit this. The problem is that when a component has an So I am just seeking to confirm my options and understanding before I redesigned some of code in TestRenderer, to hopefully get this right this time 🤞😉. Thus, is this correct?
Thanks |
Beta Was this translation helpful? Give feedback.
-
Follow up from me on this @SteveSandersonMS: The If a component in the parent component's tree, which is being visited by My solution is to wrap E.g.: private readonly object _renderTreeAccessLock = new object();
// ...
protected override void ProcessPendingRender()
{
lock (_renderTreeAccessLock)
{
base.ProcessPendingRender();
}
}
public IRenderedComponent<TComponent> FindComponent<TComponent>(int parentComponentId)
{
lock (_renderTreeAccessLock)
{
// GetCurrentRenderTreeFrames getting called here for every component under
// parentComponentId until a matching component is found.
}
} Is this a sound approach? |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Hi Blazor team
I am seeking more insight into the renderer.
Background:
In bUnit, test code (i.e. the actual
[Fact]
in xUnit parlor) runs in the synchronization context of the test framework, and the Blazor renderer runs with the default dispatcher, and thus its own synchronization context.This can cause some race conditions between test code traversing the render tree (through
GetCurrentRenderTreeFrames(componentId)
) while the renderer is asynchronously in its own thread performing re-renders, which updates the render tree. This can happen if a component asynchronously directly or indirectly triggers one or more re-renders, e.g. by awaiting services, or timers (Task.Delay).Goal:
I want to confirm my solution and understanding of the renderer before I try to improve and simplify bUnit's the code. The goal is to prevent renders while test code is traversing the render tree.
My understanding is that
void ProcessPendingRender()
is called before a any render, andUpdateDisplayAsync(in RenderBatch renderBatch)
is called after a render. Another render is not started before theTask
returned fromUpdateDisplayAsync(..)
is completed.Is this correct?
Further discussion:
I am pretty sure there would fewer be problems related to this if bUnit was not doing a complete rebuild/replace of the DOM tree when a render occurs by calling
GetCurrentRenderTreeFrames(componentId)
for every updated component and sub component affected by a render, and instead just used the contents ofRenderBatch
passed toUpdateDisplayAsync
to update an existing DOM tree, like Blazor does.To do this would however require bUnit to reimplement the TypeScript DOM tree update logic in C# with AngleSharp as its target (which I guess is doable since AngleSharp matches the DOM api pretty closely). It's on the TODO list, but there might still be a need to control updates to the DOM tree from a test perspective though.
cc. @SteveSandersonMS, @danroth27, @captainsafia.
Beta Was this translation helpful? Give feedback.
All reactions