Skip to content

feat: Add FindComponent on IElement (#153) #1738

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: v2
Choose a base branch
from

Conversation

linkdotnet
Copy link
Collaborator

@linkdotnet linkdotnet commented Jul 13, 2025

FindComponent<TComponent>

This PR allows users to call FindComponent on an IElement 1. Fixes #153

var button = cut.Find("#btn");
var owningComponent = button.FindComponent<ButtonComponent>();

It should cover all the basic scenarios (see tests), even when using ElementReferences (that should stay valid when using FindComponent).

The idea is that we can hook into the CssSelectorElementFactory (or the any other factory that inherits from IElementWrapperFactory or better the new IComponentAccessor) to retrieve the elements rendered. If that way doesn't work, we use the BunitRenderer and basically go through everything there (more expensive, but we could also solely rely on that).

The last one happens if we have a ParentComponent that gets rendered, but we do a cut.Find("...").FindComponent<ChildComponent>.

Considerations

The API forces the user to specify the desired output component type: FindComponent<TComponent> - we could also offer a version, where it "just" takes the direct parent component (as an IComponent).


1 It does not work in INode, so users can't use something like: cut.NodeList.First().FindComponent<TComponent>(); because I have no idea on how to hook into that pipeline. Maybe we some factories of Anglesharp, but I am not too deep into that at the moment.

@linkdotnet linkdotnet requested a review from egil July 13, 2025 15:30
@linkdotnet
Copy link
Collaborator Author

The name might be misleading as we have already FindComponent, but from an abstract point of view, it does the same (just on a different element). So I rolled with it.

@egil
Copy link
Member

egil commented Jul 14, 2025

So if element is created by ComponentA, then element.FindComponent<ComponentB>() will find the ComponentB if it is a child of ComponentA and element?

@egil
Copy link
Member

egil commented Jul 14, 2025

Related; i have been thinking that WaitForElement and Find could just be one method, e.g. FindAsync. If the element is not immediately there then it switches to "waiting mode". This is a lot like Playwright does it.

Makes test more resilient, e.g., if component introduces an async aspect, the test does not have to change.

@linkdotnet
Copy link
Collaborator Author

So if element is created by ComponentA, then element.FindComponent<ComponentB>() will find the ComponentB if it is a child of ComponentA and element?

So something like this:

Parent.razor

<button>Btn</button>
<ChildComponent/>

Test.cs

var cut = Render<Parent>();
var btn = cut.Find("button");

var child = btn.FindComponent<ChildComponent>();

The FindComponent would throw an exception as it can't find the component.

@linkdotnet
Copy link
Collaborator Author

linkdotnet commented Jul 14, 2025

Related; i have been thinking that WaitForElement and Find could just be one method, e.g. FindAsync. If the element is not immediately there then it switches to "waiting mode". This is a lot like Playwright does it.

Makes test more resilient, e.g., if component introduces an async aspect, the test does not have to change.

Basically that would only mean relabelling WaitForElementAsync to FindAsync (of course a bit more - but you get the idea).

The same should be true for: FindAllAsync and FindComponent(s)

@linkdotnet linkdotnet force-pushed the find-component-ext branch from 4107571 to 75bd705 Compare July 14, 2025 11:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants