Skip to content

Commit fda9b5b

Browse files
committed
refactor: clean up code
1 parent 6b80b45 commit fda9b5b

File tree

3 files changed

+153
-139
lines changed

3 files changed

+153
-139
lines changed
Lines changed: 45 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,65 +1,64 @@
1+
using Microsoft.AspNetCore.Components.Web.Virtualization;
12
using System.Diagnostics;
23
using System.Reflection;
3-
using Microsoft.AspNetCore.Components.Web.Virtualization;
44

5-
namespace Bunit.JSInterop.InvocationHandlers.Implementation
5+
namespace Bunit.JSInterop.InvocationHandlers.Implementation;
6+
7+
/// <summary>
8+
/// Represents an JSInterop handler for the <see cref="Virtualize{TItem}"/> component.
9+
/// </summary>
10+
internal sealed class VirtualizeJSRuntimeInvocationHandler : JSRuntimeInvocationHandler
611
{
7-
/// <summary>
8-
/// Represents an JSInterop handler for the <see cref="Virtualize{TItem}"/> component.
9-
/// </summary>
10-
internal sealed class VirtualizeJSRuntimeInvocationHandler : JSRuntimeInvocationHandler
12+
private const string JsFunctionsPrefix = "Blazor._internal.Virtualize.";
13+
private static readonly Lazy<(PropertyInfo, MethodInfo)> VirtualizeReflection = new(() =>
1114
{
12-
private const string JsFunctionsPrefix = "Blazor._internal.Virtualize.";
13-
private static readonly Lazy<(PropertyInfo, MethodInfo)> VirtualizeReflection = new(() =>
14-
{
15-
var virtualizeJsInteropType = typeof(Virtualize<>)
16-
.Assembly
17-
.GetType("Microsoft.AspNetCore.Components.Web.Virtualization.VirtualizeJsInterop")
18-
?? throw new InvalidOperationException("Did not find the VirtualizeJsInterop in the expected namespace/assembly.");
15+
var virtualizeJsInteropType = typeof(Virtualize<>)
16+
.Assembly
17+
.GetType("Microsoft.AspNetCore.Components.Web.Virtualization.VirtualizeJsInterop")
18+
?? throw new InvalidOperationException("Did not find the VirtualizeJsInterop in the expected namespace/assembly.");
1919

20-
var dotNetObjectReferenceVirtualizeJsInteropType = typeof(DotNetObjectReference<>).MakeGenericType(virtualizeJsInteropType);
20+
var dotNetObjectReferenceVirtualizeJsInteropType = typeof(DotNetObjectReference<>).MakeGenericType(virtualizeJsInteropType);
2121

22-
var dotNetObjectReferenceValuePropertyInfo = dotNetObjectReferenceVirtualizeJsInteropType.GetProperty("Value", BindingFlags.Public | BindingFlags.Instance)
23-
?? throw new InvalidOperationException("Did not find the Value property on the DotNetObjectReference<VirtualizeJsInterop> type.");
22+
var dotNetObjectReferenceValuePropertyInfo = dotNetObjectReferenceVirtualizeJsInteropType.GetProperty("Value", BindingFlags.Public | BindingFlags.Instance)
23+
?? throw new InvalidOperationException("Did not find the Value property on the DotNetObjectReference<VirtualizeJsInterop> type.");
2424

25-
var onSpacerBeforeVisibleMethodInfo = virtualizeJsInteropType.GetMethod("OnSpacerBeforeVisible")
26-
?? throw new InvalidOperationException("Did not find the OnSpacerBeforeVisible method on the VirtualizeJsInterop type.");
25+
var onSpacerBeforeVisibleMethodInfo = virtualizeJsInteropType.GetMethod("OnSpacerBeforeVisible")
26+
?? throw new InvalidOperationException("Did not find the OnSpacerBeforeVisible method on the VirtualizeJsInterop type.");
2727

28-
return (dotNetObjectReferenceValuePropertyInfo, onSpacerBeforeVisibleMethodInfo);
29-
});
28+
return (dotNetObjectReferenceValuePropertyInfo, onSpacerBeforeVisibleMethodInfo);
29+
});
3030

31-
internal VirtualizeJSRuntimeInvocationHandler()
32-
: base(i => i.Identifier.StartsWith(JsFunctionsPrefix, StringComparison.Ordinal), isCatchAllHandler: false)
33-
{ }
31+
internal VirtualizeJSRuntimeInvocationHandler()
32+
: base(i => i.Identifier.StartsWith(JsFunctionsPrefix, StringComparison.Ordinal), isCatchAllHandler: false)
33+
{ }
3434

35-
/// <inheritdoc/>
36-
protected internal override Task<Microsoft.JSInterop.Infrastructure.IJSVoidResult> HandleAsync(JSRuntimeInvocation invocation)
35+
/// <inheritdoc/>
36+
protected internal override Task<Microsoft.JSInterop.Infrastructure.IJSVoidResult> HandleAsync(JSRuntimeInvocation invocation)
37+
{
38+
if (!invocation.Identifier.Equals(JsFunctionsPrefix + "dispose", StringComparison.Ordinal))
3739
{
38-
if (!invocation.Identifier.Equals(JsFunctionsPrefix + "dispose", StringComparison.Ordinal))
39-
{
40-
Debug.Assert(invocation.Identifier.Equals(JsFunctionsPrefix + "init", StringComparison.Ordinal));
41-
Debug.Assert(invocation.Arguments.Count == 3);
42-
Debug.Assert(invocation.Arguments[0] is not null);
40+
Debug.Assert(invocation.Identifier.Equals(JsFunctionsPrefix + "init", StringComparison.Ordinal));
41+
Debug.Assert(invocation.Arguments.Count == 3);
42+
Debug.Assert(invocation.Arguments[0] is not null);
4343

44-
InvokeOnSpacerBeforeVisible(invocation.Arguments[0]!);
44+
InvokeOnSpacerBeforeVisible(invocation.Arguments[0]!);
4545

46-
SetVoidResult();
47-
}
48-
49-
return base.HandleAsync(invocation);
46+
SetVoidResult();
5047
}
5148

52-
private static void InvokeOnSpacerBeforeVisible(object dotNetObjectReference)
49+
return base.HandleAsync(invocation);
50+
}
51+
52+
private static void InvokeOnSpacerBeforeVisible(object dotNetObjectReference)
53+
{
54+
var (dotNetObjectReferenceValuePropertyInfo, onSpacerBeforeVisibleMethodInfo) = VirtualizeReflection.Value;
55+
var virtualizeJsInterop = dotNetObjectReferenceValuePropertyInfo.GetValue(dotNetObjectReference);
56+
var parameters = new object[]
5357
{
54-
var (dotNetObjectReferenceValuePropertyInfo, onSpacerBeforeVisibleMethodInfo) = VirtualizeReflection.Value;
55-
var virtualizeJsInterop = dotNetObjectReferenceValuePropertyInfo.GetValue(dotNetObjectReference);
56-
var parameters = new object[]
57-
{
58-
0f, /* spacerSize */
59-
0f, /* spacerSeparation */
60-
1_000_000_000f, /* containerSize - very large number to ensure all items are loaded at once */
61-
};
62-
onSpacerBeforeVisibleMethodInfo.Invoke(virtualizeJsInterop, parameters);
63-
}
58+
0f, /* spacerSize */
59+
0f, /* spacerSeparation */
60+
1_000_000_000f, /* containerSize - very large number to ensure all items are loaded at once */
61+
};
62+
onSpacerBeforeVisibleMethodInfo.Invoke(virtualizeJsInterop, parameters);
6463
}
6564
}

src/bunit/JSInterop/InvocationHandlers/JSRuntimeInvocationHandler.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@ namespace Bunit;
33
/// <summary>
44
/// Represents a handler for an invocation of a JavaScript function which returns nothing, with specific arguments.
55
/// </summary>
6-
public class JSRuntimeInvocationHandler
7-
: JSRuntimeInvocationHandlerBase<Microsoft.JSInterop.Infrastructure.IJSVoidResult>
6+
public class JSRuntimeInvocationHandler : JSRuntimeInvocationHandlerBase<Microsoft.JSInterop.Infrastructure.IJSVoidResult>
87
{
98
/// <inheritdoc/>
109
public override sealed bool IsVoidResultHandler => true;

src/bunit/Rendering/BunitRenderer.cs

Lines changed: 107 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1+
using Microsoft.Extensions.Logging;
12
using System.Collections.Concurrent;
23
using System.Diagnostics;
34
using System.Reflection;
45
using System.Runtime.CompilerServices;
56
using System.Runtime.ExceptionServices;
6-
using Microsoft.Extensions.Logging;
77

88
namespace Bunit.Rendering;
99

@@ -12,9 +12,10 @@ namespace Bunit.Rendering;
1212
/// </summary>
1313
public sealed class BunitRenderer : Renderer
1414
{
15+
private static readonly ConcurrentDictionary<Type, ConstructorInfo> ComponentActivatorCache = new();
16+
1517
private readonly BunitServiceProvider services;
1618
private readonly List<Task> disposalTasks = [];
17-
private static readonly ConcurrentDictionary<Type, ConstructorInfo> componentActivatorCache = new();
1819

1920
[UnsafeAccessor(UnsafeAccessorKind.Field, Name = "_isBatchInProgress")]
2021
private static extern ref bool GetIsBatchInProgressField(Renderer renderer);
@@ -60,22 +61,22 @@ private bool IsBatchInProgress
6061
internal int RenderCount { get; }
6162

6263
#if NET9_0_OR_GREATER
63-
private RendererInfo? rendererInfo;
64-
65-
/// <inheritdoc/>
66-
[SuppressMessage(
67-
"Design",
68-
"CA1065:Do not raise exceptions in unexpected locations",
69-
Justification = "The exception is raised to guide users."
70-
)]
71-
protected override RendererInfo RendererInfo =>
72-
rendererInfo ?? throw new MissingRendererInfoException();
73-
74-
/// <inheritdoc/>
75-
public void SetRendererInfo(RendererInfo? rendererInfo)
76-
{
77-
this.rendererInfo = rendererInfo;
78-
}
64+
private RendererInfo? rendererInfo;
65+
66+
/// <inheritdoc/>
67+
[SuppressMessage(
68+
"Design",
69+
"CA1065:Do not raise exceptions in unexpected locations",
70+
Justification = "The exception is raised to guide users."
71+
)]
72+
protected override RendererInfo RendererInfo =>
73+
rendererInfo ?? throw new MissingRendererInfoException();
74+
75+
/// <inheritdoc/>
76+
public void SetRendererInfo(RendererInfo? rendererInfo)
77+
{
78+
this.rendererInfo = rendererInfo;
79+
}
7980
#endif
8081

8182
/// <summary>
@@ -112,6 +113,21 @@ public BunitRenderer(BunitServiceProvider services, ILoggerFactory loggerFactory
112113
ElementReferenceContext = new WebElementReferenceContext(services.GetRequiredService<IJSRuntime>());
113114
}
114115

116+
/// <summary>
117+
/// Renders a <typeparamref name="TComponent"/> with the parameters build with the <paramref name="parameterBuilder"/> passed to it.
118+
/// </summary>
119+
/// <typeparam name = "TComponent" > The type of component to render.</typeparam>
120+
/// <param name="parameterBuilder">The a builder to create parameters to pass to the component.</param>
121+
/// <returns>A <see cref="RenderedComponent{TComponent}"/> that provides access to the rendered component.</returns>
122+
public IRenderedComponent<TComponent> Render<TComponent>(Action<ComponentParameterCollectionBuilder<TComponent>>? parameterBuilder = null)
123+
where TComponent : IComponent
124+
{
125+
var builder = new ComponentParameterCollectionBuilder<TComponent>(parameterBuilder);
126+
var renderFragment = builder.Build().ToRenderFragment<TComponent>();
127+
var renderedComponent = RenderFragment(renderFragment);
128+
return renderedComponent.FindComponent<TComponent>();
129+
}
130+
115131
/// <summary>
116132
/// Renders the <paramref name="renderFragment"/>.
117133
/// </summary>
@@ -255,7 +271,7 @@ protected override ComponentState CreateComponentState(int componentId, ICompone
255271

256272
object CreateComponentInstance()
257273
{
258-
var constructorInfo = componentActivatorCache.GetOrAdd(renderedComponentType, type
274+
var constructorInfo = ComponentActivatorCache.GetOrAdd(renderedComponentType, type
259275
=> type.GetConstructor(
260276
[
261277
typeof(BunitRenderer),
@@ -281,78 +297,78 @@ protected override IComponent ResolveComponentForRenderMode(Type componentType,
281297
}
282298

283299
#if NET9_0_OR_GREATER
284-
/// <inheritdoc/>
285-
protected override IComponentRenderMode? GetComponentRenderMode(IComponent component)
286-
{
287-
ArgumentNullException.ThrowIfNull(component);
288-
289-
// Search from the current component all the way up the render tree.
290-
// All components must have the same render mode specified (or none at all).
291-
// Return the render mode that is found after checking the full tree.
292-
return GetAndValidateRenderMode(component, childRenderMode: null);
293-
294-
IComponentRenderMode? GetAndValidateRenderMode(
295-
IComponent component,
296-
IComponentRenderMode? childRenderMode
297-
)
298-
{
299-
var componentState = GetComponentState(component);
300-
var renderMode = GetRenderModeForComponent(componentState);
301-
302-
if (
303-
childRenderMode is not null
304-
&& renderMode is not null
305-
&& childRenderMode != renderMode
306-
)
307-
{
308-
throw new RenderModeMisMatchException();
309-
}
310-
311-
return componentState.ParentComponentState is null
312-
? renderMode ?? childRenderMode
313-
: GetAndValidateRenderMode(
314-
componentState.ParentComponentState.Component,
315-
renderMode ?? childRenderMode
316-
);
317-
}
318-
319-
IComponentRenderMode? GetRenderModeForComponent(ComponentState componentState)
320-
{
321-
var renderModeAttribute = componentState.Component
322-
.GetType()
323-
.GetCustomAttribute<RenderModeAttribute>();
324-
if (renderModeAttribute is { Mode: not null })
325-
{
326-
return renderModeAttribute.Mode;
327-
}
328-
329-
if (componentState.ParentComponentState is not null)
330-
{
331-
var parentFrames = GetCurrentRenderTreeFrames(
332-
componentState.ParentComponentState.ComponentId
333-
);
334-
var foundComponentStart = false;
335-
for (var i = 0; i < parentFrames.Count; i++)
336-
{
337-
ref var frame = ref parentFrames.Array[i];
338-
339-
if (frame.FrameType is RenderTreeFrameType.Component)
340-
{
341-
foundComponentStart = frame.ComponentId == componentState.ComponentId;
342-
}
343-
else if (
344-
foundComponentStart
345-
&& frame.FrameType is RenderTreeFrameType.ComponentRenderMode
346-
)
347-
{
348-
return frame.ComponentRenderMode;
349-
}
350-
}
351-
}
352-
353-
return null;
354-
}
355-
}
300+
/// <inheritdoc/>
301+
protected override IComponentRenderMode? GetComponentRenderMode(IComponent component)
302+
{
303+
ArgumentNullException.ThrowIfNull(component);
304+
305+
// Search from the current component all the way up the render tree.
306+
// All components must have the same render mode specified (or none at all).
307+
// Return the render mode that is found after checking the full tree.
308+
return GetAndValidateRenderMode(component, childRenderMode: null);
309+
310+
IComponentRenderMode? GetAndValidateRenderMode(
311+
IComponent component,
312+
IComponentRenderMode? childRenderMode
313+
)
314+
{
315+
var componentState = GetComponentState(component);
316+
var renderMode = GetRenderModeForComponent(componentState);
317+
318+
if (
319+
childRenderMode is not null
320+
&& renderMode is not null
321+
&& childRenderMode != renderMode
322+
)
323+
{
324+
throw new RenderModeMisMatchException();
325+
}
326+
327+
return componentState.ParentComponentState is null
328+
? renderMode ?? childRenderMode
329+
: GetAndValidateRenderMode(
330+
componentState.ParentComponentState.Component,
331+
renderMode ?? childRenderMode
332+
);
333+
}
334+
335+
IComponentRenderMode? GetRenderModeForComponent(ComponentState componentState)
336+
{
337+
var renderModeAttribute = componentState.Component
338+
.GetType()
339+
.GetCustomAttribute<RenderModeAttribute>();
340+
if (renderModeAttribute is { Mode: not null })
341+
{
342+
return renderModeAttribute.Mode;
343+
}
344+
345+
if (componentState.ParentComponentState is not null)
346+
{
347+
var parentFrames = GetCurrentRenderTreeFrames(
348+
componentState.ParentComponentState.ComponentId
349+
);
350+
var foundComponentStart = false;
351+
for (var i = 0; i < parentFrames.Count; i++)
352+
{
353+
ref var frame = ref parentFrames.Array[i];
354+
355+
if (frame.FrameType is RenderTreeFrameType.Component)
356+
{
357+
foundComponentStart = frame.ComponentId == componentState.ComponentId;
358+
}
359+
else if (
360+
foundComponentStart
361+
&& frame.FrameType is RenderTreeFrameType.ComponentRenderMode
362+
)
363+
{
364+
return frame.ComponentRenderMode;
365+
}
366+
}
367+
}
368+
369+
return null;
370+
}
371+
}
356372
#endif
357373

358374
/// <inheritdoc/>

0 commit comments

Comments
 (0)