-
-
Notifications
You must be signed in to change notification settings - Fork 121
Expand file tree
/
Copy pathBunitJSInteropSetupExtensions.cs
More file actions
173 lines (153 loc) · 10.2 KB
/
Copy pathBunitJSInteropSetupExtensions.cs
File metadata and controls
173 lines (153 loc) · 10.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
namespace Bunit;
/// <summary>
/// Helper methods for creating invocation handlers and adding the to a <see cref="BunitJSInterop"/>.
/// </summary>
public static partial class BunitJSInteropSetupExtensions
{
/// <summary>
/// Configure a JSInterop invocation handler for an <c>InvokeAsync<TResult></c> call with arguments
/// passing the <paramref name="invocationMatcher"/> test.
/// </summary>
/// <typeparam name="TResult">The result type of the invocation.</typeparam>
/// <param name="jsInterop">The bUnit JSInterop to setup the invocation handling with.</param>
/// <param name="invocationMatcher">A matcher that is passed an <see cref="JSRuntimeInvocation"/>. If it returns true the invocation is matched.</param>
/// <param name="isCatchAllHandler">Set to true if the created handler is a catch all handler, that should only be used if there are no other non-catch all handlers available.</param>
/// <returns>A <see cref="JSRuntimeInvocationHandler{TResult}"/>.</returns>
public static JSRuntimeInvocationHandler<TResult> Setup<TResult>(this BunitJSInterop jsInterop, InvocationMatcher invocationMatcher, bool isCatchAllHandler = false)
{
if (jsInterop is null)
throw new ArgumentNullException(nameof(jsInterop));
#if NET5_0_OR_GREATER
EnsureResultNotIJSObjectReference<TResult>();
#endif
var result = new JSRuntimeInvocationHandler<TResult>(invocationMatcher, isCatchAllHandler);
jsInterop.AddInvocationHandler(result);
return result;
}
/// <summary>
/// Configure a JSInterop invocation handler with the <paramref name="identifier"/> and arguments
/// passing the <paramref name="invocationMatcher"/> test.
/// </summary>
/// <typeparam name="TResult">The result type of the invocation.</typeparam>
/// <param name="jsInterop">The bUnit JSInterop to setup the invocation handling with.</param>
/// <param name="identifier">The identifier to setup a response for.</param>
/// <param name="invocationMatcher">A matcher that is passed an <see cref="JSRuntimeInvocation"/> associated with the<paramref name="identifier"/>. If it returns true the invocation is matched.</param>
/// <returns>A <see cref="JSRuntimeInvocationHandler{TResult}"/>.</returns>
public static JSRuntimeInvocationHandler<TResult> Setup<TResult>(this BunitJSInterop jsInterop, string identifier, InvocationMatcher invocationMatcher)
=> Setup<TResult>(jsInterop, inv => identifier.Equals(inv.Identifier, StringComparison.Ordinal) && invocationMatcher(inv));
/// <summary>
/// Configure a JSInterop invocation handler with the <paramref name="identifier"/> and <paramref name="arguments"/>.
/// </summary>
/// <typeparam name="TResult">The type of value to match with in a InvokeAsync<TResult> call.</typeparam>
/// <param name="jsInterop">The bUnit JSInterop to setup the invocation handling with.</param>
/// <param name="identifier">The identifier to setup a response for.</param>
/// <param name="arguments">The arguments that an invocation to <paramref name="identifier"/> should match.</param>
/// <returns>A <see cref="JSRuntimeInvocationHandler{TResult}"/>.</returns>
public static JSRuntimeInvocationHandler<TResult> Setup<TResult>(this BunitJSInterop jsInterop, string identifier, params object?[]? arguments)
=> Setup<TResult>(jsInterop, identifier, invocation => invocation.Arguments.SequenceEqual(arguments ?? Array.Empty<object?>()));
/// <summary>
/// Configure a catch all JSInterop invocation handler for a specific return type.
/// This will match only on the <typeparamref name="TResult"/>, and any arguments passed to
/// <see cref="IJSRuntime.InvokeAsync{TValue}(string, object[])"/>.
/// </summary>
/// <typeparam name="TResult">The result type of the invocation.</typeparam>
/// <param name="jsInterop">The bUnit JSInterop to setup the invocation handling with.</param>
/// <returns>A <see cref="JSRuntimeInvocationHandler{TResult}"/>.</returns>
public static JSRuntimeInvocationHandler<TResult> Setup<TResult>(this BunitJSInterop jsInterop)
=> Setup<TResult>(jsInterop, _ => true, isCatchAllHandler: true);
/// <summary>
/// Configure a JSInterop invocation handler for an <c>InvokeVoidAsync</c> call with arguments
/// passing the <paramref name="invocationMatcher"/> test, that should not receive any result.
/// </summary>
/// <param name="jsInterop">The bUnit JSInterop to setup the invocation handling with.</param>
/// <param name="invocationMatcher">A matcher that is passed an <see cref="JSRuntimeInvocation"/>. If it returns true the invocation is matched.</param>
/// <param name="isCatchAllHandler">Set to true if the created handler is a catch all handler, that should only be used if there are no other non-catch all handlers available.</param>
/// <returns>A <see cref="JSRuntimeInvocationHandler"/>.</returns>
public static JSRuntimeInvocationHandler SetupVoid(this BunitJSInterop jsInterop, InvocationMatcher invocationMatcher, bool isCatchAllHandler = false)
{
if (jsInterop is null)
throw new ArgumentNullException(nameof(jsInterop));
var result = new JSRuntimeInvocationHandler(invocationMatcher, isCatchAllHandler);
jsInterop.AddInvocationHandler(result);
return result;
}
/// <summary>
/// Configure a JSInterop invocation handler with the <paramref name="identifier"/> and arguments
/// passing the <paramref name="invocationMatcher"/> test, that should not receive any result.
/// </summary>
/// <param name="jsInterop">The bUnit JSInterop to setup the invocation handling with.</param>
/// <param name="identifier">The identifier to setup a response for.</param>
/// <param name="invocationMatcher">A matcher that is passed an <see cref="JSRuntimeInvocation"/> associated with the<paramref name="identifier"/>. If it returns true the invocation is matched.</param>
/// <returns>A <see cref="JSRuntimeInvocationHandler"/>.</returns>
public static JSRuntimeInvocationHandler SetupVoid(this BunitJSInterop jsInterop, string identifier, InvocationMatcher invocationMatcher)
=> SetupVoid(jsInterop, inv => identifier.Equals(inv.Identifier, StringComparison.Ordinal) && invocationMatcher(inv));
/// <summary>
/// Configure a JSInterop invocation handler with the <paramref name="identifier"/>
/// and <paramref name="arguments"/>, that should not receive any result.
/// </summary>
/// <param name="jsInterop">The bUnit JSInterop to setup the invocation handling with.</param>
/// <param name="identifier">The identifier to setup a response for.</param>
/// <param name="arguments">The arguments that an invocation to <paramref name="identifier"/> should match.</param>
/// <returns>A <see cref="JSRuntimeInvocationHandler"/>.</returns>
public static JSRuntimeInvocationHandler SetupVoid(this BunitJSInterop jsInterop, string identifier, params object?[]? arguments)
=> SetupVoid(jsInterop, identifier, invocation => invocation.Arguments.SequenceEqual(arguments ?? Array.Empty<object?>()));
/// <summary>
/// Configure a catch all JSInterop invocation handler, that should not receive any result.
/// </summary>
/// <param name="jsInterop">The bUnit JSInterop to setup the invocation handling with.</param>
/// <returns>A <see cref="JSRuntimeInvocationHandler"/>.</returns>
public static JSRuntimeInvocationHandler SetupVoid(this BunitJSInterop jsInterop)
=> SetupVoid(jsInterop, _ => true, isCatchAllHandler: true);
/// <summary>
/// Looks through the registered handlers and returns the latest registered that can handle
/// the provided <paramref name="identifier"/> and <paramref name="arguments"/>, and that
/// will return <typeparamref name="TResult"/>.
/// </summary>
/// <param name="jsInterop">The bUnit JSInterop to setup the invocation handling with.</param>
/// <param name="identifier">The identifier the handler should match with.</param>
/// <param name="arguments">The arguments that an invocation to <paramref name="identifier"/> should match.</param>
/// <typeparam name="TResult">The result type of the invocation.</typeparam>
/// <returns>Returns the <see cref="JSRuntimeInvocationHandler{TResult}"/> or null if no one is found.</returns>
public static JSRuntimeInvocationHandler<TResult>? TryGetInvokeHandler<TResult>(this BunitJSInterop jsInterop, string identifier, params object?[]? arguments)
{
if (jsInterop is null)
throw new ArgumentNullException(nameof(jsInterop));
return jsInterop.TryGetHandlerFor<TResult>(
new JSRuntimeInvocation(
identifier,
default,
arguments,
typeof(TResult),
string.Empty)) as JSRuntimeInvocationHandler<TResult>;
}
/// <summary>
/// Looks through the registered handlers and returns the latest registered that can handle
/// the provided <paramref name="identifier"/> and <paramref name="arguments"/>, and that returns a "void" result.
/// </summary>
/// <param name="jsInterop">The bUnit JSInterop to setup the invocation handling with.</param>
/// <param name="identifier">The identifier the handler should match with.</param>
/// <param name="arguments">The arguments that an invocation to <paramref name="identifier"/> should match.</param>
/// <returns>Returns the <see cref="JSRuntimeInvocationHandler"/> or null if no one is found.</returns>
public static JSRuntimeInvocationHandler? TryGetInvokeVoidHandler(this BunitJSInterop jsInterop, string identifier, params object?[]? arguments)
{
if (jsInterop is null)
throw new ArgumentNullException(nameof(jsInterop));
var invocation = new JSRuntimeInvocation(identifier, default, arguments, typeof(object), string.Empty);
#if !NET6_0_OR_GREATER
return jsInterop.TryGetHandlerFor<object>(invocation, x => x.IsVoidResultHandler) as JSRuntimeInvocationHandler;
#else
return jsInterop.TryGetHandlerFor<Microsoft.JSInterop.Infrastructure.IJSVoidResult>(invocation, x => x.IsVoidResultHandler) as JSRuntimeInvocationHandler;
#endif
}
#if NET5_0_OR_GREATER
private static void EnsureResultNotIJSObjectReference<TResult>()
{
const string UseSetupModuleErrorMessage = "Use one of the SetupModule() methods instead to set up an invocation handler that returns an IJSObjectReference.";
var resultType = typeof(TResult);
if (resultType == typeof(IJSObjectReference))
throw new ArgumentException(UseSetupModuleErrorMessage);
if (resultType == typeof(Microsoft.JSInterop.Implementation.JSObjectReference))
throw new ArgumentException(UseSetupModuleErrorMessage);
}
#endif
}