77using System . Linq ;
88using System . Threading . Tasks ;
99using Egil . RazorComponents . Testing . Extensions ;
10+ using AngleSharp . Css . Dom ;
1011
1112namespace Egil . RazorComponents . Testing
1213{
@@ -32,7 +33,7 @@ public ContainerComponent(TestRenderer renderer)
3233 {
3334 if ( renderer is null ) throw new ArgumentNullException ( nameof ( renderer ) ) ;
3435 _renderer = renderer ;
35- ComponentId = _renderer . AttachTestRootComponent ( this ) ;
36+ ComponentId = _renderer . AttachTestRootComponent ( this ) ;
3637 }
3738
3839 /// <inheritdoc/>
@@ -58,17 +59,14 @@ public void Render(RenderFragment renderFragment)
5859 /// component is found, its child content is also searched recursively.
5960 /// </summary>
6061 /// <typeparam name="TComponent">The type of component to find</typeparam>
61- /// <exception cref="InvalidOperationException">When there are more than one component of type <typeparamref name="TComponent"/> found or if none are found.</exception>
62+ /// <exception cref="InvalidOperationException">When a component of type <typeparamref name="TComponent"/> was not found.</exception>
6263 public ( int Id , TComponent Component ) GetComponent < TComponent > ( ) where TComponent : IComponent
6364 {
64- var result = GetComponents < TComponent > ( ) ;
65-
66- if ( result . Count == 1 )
67- return result [ 0 ] ;
68- else if ( result . Count == 0 )
69- throw new InvalidOperationException ( $ "No components of type { typeof ( TComponent ) } were found in the render tree.") ;
65+ var result = GetComponent < TComponent > ( ComponentId ) ;
66+ if ( result . HasValue )
67+ return result . Value ;
7068 else
71- throw new InvalidOperationException ( $ "More than one component of type { typeof ( TComponent ) } was found in the render tree.") ;
69+ throw new InvalidOperationException ( $ "No components of type { typeof ( TComponent ) } were found in the render tree.") ;
7270 }
7371
7472 /// <summary>
@@ -84,7 +82,7 @@ public void Render(RenderFragment renderFragment)
8482 var ownFrames = _renderer . GetCurrentRenderTreeFrames ( componentId ) ;
8583 if ( ownFrames . Count == 0 )
8684 {
87- throw new InvalidOperationException ( $ " { nameof ( ContainerComponent ) } hasn't yet rendered" ) ;
85+ return Array . Empty < ( int Id , TComponent Component ) > ( ) ;
8886 }
8987
9088 var result = new List < ( int Id , TComponent Component ) > ( ) ;
@@ -97,20 +95,32 @@ public void Render(RenderFragment renderFragment)
9795 {
9896 result . Add ( ( frame . ComponentId , component ) ) ;
9997 }
100- else if ( frame . Component . IsCascadingValueComponent ( ) )
98+ result . AddRange ( GetComponents < TComponent > ( frame . ComponentId ) ) ;
99+ }
100+ }
101+
102+ return result ;
103+ }
104+
105+ private ( int Id , TComponent Component ) ? GetComponent < TComponent > ( int componentId ) where TComponent : IComponent
106+ {
107+ var ownFrames = _renderer . GetCurrentRenderTreeFrames ( componentId ) ;
108+
109+ for ( int i = 0 ; i < ownFrames . Count ; i ++ )
110+ {
111+ ref var frame = ref ownFrames . Array [ i ] ;
112+ if ( frame . FrameType == RenderTreeFrameType . Component )
113+ {
114+ if ( frame . Component is TComponent component )
101115 {
102- // It seems as if CascadingValue components works a little different
103- // than regular components with child content is not rendered
104- // and available via GetCurrentRenderTreeFrames for the componentId
105- // of the component that had the CascadingValue as a child.
106- // Thus we call GetComponents recursively with the CascadingValue's
107- // componentId to see if the TComponent is inside it.
108- result . AddRange ( GetComponents < TComponent > ( frame . ComponentId ) ) ;
116+ return ( frame . ComponentId , component ) ;
109117 }
118+ var result = GetComponent < TComponent > ( frame . ComponentId ) ;
119+ if ( result != null ) return result ;
110120 }
111121 }
112122
113- return result ;
123+ return null ;
114124 }
115125 }
116126}
0 commit comments