Skip to content

Commit fdacc1d

Browse files
committed
Added UAuthLoginForm Tests
1 parent 6ba4aab commit fdacc1d

File tree

2 files changed

+215
-0
lines changed

2 files changed

+215
-0
lines changed
Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
1+
using Bunit;
2+
using CodeBeam.UltimateAuth.Client;
3+
using CodeBeam.UltimateAuth.Client.Blazor;
4+
using CodeBeam.UltimateAuth.Client.Options;
5+
using CodeBeam.UltimateAuth.Client.Services;
6+
using CodeBeam.UltimateAuth.Core.Abstractions;
7+
using CodeBeam.UltimateAuth.Core.Contracts;
8+
using CodeBeam.UltimateAuth.Core.Domain;
9+
using CodeBeam.UltimateAuth.Core.Errors;
10+
using FluentAssertions;
11+
using Microsoft.AspNetCore.Components;
12+
using Microsoft.Extensions.DependencyInjection;
13+
using Microsoft.Extensions.Options;
14+
using Moq;
15+
16+
namespace CodeBeam.UltimateAuth.Tests.Unit;
17+
18+
public class UAuthLoginFormTests
19+
{
20+
[Fact]
21+
public void Should_Render_Form()
22+
{
23+
using var ctx = new BunitContext();
24+
25+
ctx.Services.AddSingleton(Mock.Of<IDeviceIdProvider>());
26+
ctx.Services.AddSingleton(Mock.Of<IUAuthClient>());
27+
ctx.Services.AddSingleton(Mock.Of<IHubCredentialResolver>());
28+
ctx.Services.AddSingleton(Mock.Of<IHubFlowReader>());
29+
ctx.Services.AddSingleton(Mock.Of<IHubCapabilities>());
30+
ctx.Services.AddSingleton<IOptions<UAuthClientOptions>>(Options.Create(new UAuthClientOptions()));
31+
32+
var cut = ctx.Render<UAuthLoginForm>();
33+
34+
cut.Find("form").Should().NotBeNull();
35+
}
36+
37+
[Fact]
38+
public void Should_Render_Identifier_And_Secret_Inputs()
39+
{
40+
using var ctx = new BunitContext();
41+
42+
ctx.Services.AddSingleton(Mock.Of<IDeviceIdProvider>());
43+
ctx.Services.AddSingleton(Mock.Of<IUAuthClient>());
44+
ctx.Services.AddSingleton(Mock.Of<IHubCredentialResolver>());
45+
ctx.Services.AddSingleton(Mock.Of<IHubFlowReader>());
46+
ctx.Services.AddSingleton(Mock.Of<IHubCapabilities>());
47+
ctx.Services.AddSingleton<IOptions<UAuthClientOptions>>(Options.Create(new UAuthClientOptions()));
48+
49+
var cut = ctx.Render<UAuthLoginForm>(p => p
50+
.Add(x => x.Identifier, "user")
51+
.Add(x => x.Secret, "pass"));
52+
53+
cut.Markup.Should().Contain("name=\"Identifier\"");
54+
cut.Markup.Should().Contain("name=\"Secret\"");
55+
}
56+
57+
[Fact]
58+
public async Task Submit_Should_Call_TryLogin()
59+
{
60+
using var ctx = new BunitContext();
61+
62+
var flowMock = new Mock<IFlowClient>();
63+
64+
flowMock.Setup(x => x.TryLoginAsync(
65+
It.IsAny<LoginRequest>(),
66+
It.IsAny<UAuthSubmitMode>(),
67+
It.IsAny<string>()))
68+
.ReturnsAsync(new TryLoginResult { Success = true });
69+
70+
var clientMock = new Mock<IUAuthClient>();
71+
clientMock.Setup(x => x.Flows).Returns(flowMock.Object);
72+
73+
ctx.Services.AddSingleton(clientMock.Object);
74+
ctx.Services.AddSingleton(Mock.Of<IDeviceIdProvider>());
75+
ctx.Services.AddSingleton(Mock.Of<IHubCredentialResolver>());
76+
ctx.Services.AddSingleton(Mock.Of<IHubFlowReader>());
77+
ctx.Services.AddSingleton(Mock.Of<IHubCapabilities>());
78+
ctx.Services.AddSingleton<IOptions<UAuthClientOptions>>(Options.Create(new UAuthClientOptions()));
79+
80+
var cut = ctx.Render<UAuthLoginForm>(p => p
81+
.Add(x => x.Identifier, "user")
82+
.Add(x => x.Secret, "pass"));
83+
84+
await cut.Instance.SubmitAsync();
85+
86+
flowMock.Verify(x =>
87+
x.TryLoginAsync(It.IsAny<LoginRequest>(), It.IsAny<UAuthSubmitMode>(), It.IsAny<string>()),
88+
Times.Once);
89+
}
90+
91+
[Fact]
92+
public async Task Submit_Should_Throw_When_Missing_Credentials()
93+
{
94+
using var ctx = new BunitContext();
95+
96+
ctx.Services.AddSingleton(Mock.Of<IUAuthClient>());
97+
ctx.Services.AddSingleton(Mock.Of<IDeviceIdProvider>());
98+
ctx.Services.AddSingleton(Mock.Of<IHubCredentialResolver>());
99+
ctx.Services.AddSingleton(Mock.Of<IHubFlowReader>());
100+
ctx.Services.AddSingleton(Mock.Of<IHubCapabilities>());
101+
ctx.Services.AddSingleton<IOptions<UAuthClientOptions>>(Options.Create(new UAuthClientOptions()));
102+
103+
var cut = ctx.Render<UAuthLoginForm>();
104+
105+
Func<Task> act = async () => await cut.Instance.SubmitAsync();
106+
107+
await act.Should().ThrowAsync<UAuthValidationException>();
108+
}
109+
110+
[Fact]
111+
public async Task SubmitPkce_Should_Call_TryCompletePkce()
112+
{
113+
using var ctx = new BunitContext();
114+
115+
var flowMock = new Mock<IFlowClient>();
116+
117+
flowMock.Setup(x => x.TryCompletePkceLoginAsync(
118+
It.IsAny<PkceCompleteRequest>(),
119+
It.IsAny<UAuthSubmitMode>()))
120+
.ReturnsAsync(new TryPkceLoginResult { Success = true });
121+
122+
var clientMock = new Mock<IUAuthClient>();
123+
clientMock.Setup(x => x.Flows).Returns(flowMock.Object);
124+
125+
var credResolver = new Mock<IHubCredentialResolver>();
126+
credResolver.Setup(x => x.ResolveAsync(It.IsAny<HubSessionId>()))
127+
.ReturnsAsync(new HubCredentials
128+
{
129+
AuthorizationCode = "code",
130+
CodeVerifier = "verifier"
131+
});
132+
133+
var capabilities = new Mock<IHubCapabilities>();
134+
capabilities.Setup(x => x.SupportsPkce).Returns(true);
135+
136+
ctx.Services.AddSingleton(clientMock.Object);
137+
ctx.Services.AddSingleton(Mock.Of<IDeviceIdProvider>());
138+
ctx.Services.AddSingleton(credResolver.Object);
139+
ctx.Services.AddSingleton(Mock.Of<IHubFlowReader>());
140+
ctx.Services.AddSingleton(capabilities.Object);
141+
ctx.Services.AddSingleton<IOptions<UAuthClientOptions>>(Options.Create(new UAuthClientOptions()));
142+
143+
var hubSessionId = HubSessionId.New();
144+
145+
var cut = ctx.Render<UAuthLoginForm>(p => p
146+
.Add(x => x.Identifier, "user")
147+
.Add(x => x.Secret, "pass")
148+
.Add(x => x.LoginType, UAuthLoginType.Pkce)
149+
.Add(x => x.HubSessionId, hubSessionId));
150+
151+
await cut.InvokeAsync(() => Task.CompletedTask);
152+
await cut.Instance.SubmitAsync();
153+
154+
flowMock.Verify(x =>
155+
x.TryCompletePkceLoginAsync(It.IsAny<PkceCompleteRequest>(), It.IsAny<UAuthSubmitMode>()),
156+
Times.Once);
157+
}
158+
159+
[Fact]
160+
public async Task Should_Invoke_OnTryResult()
161+
{
162+
using var ctx = new BunitContext();
163+
164+
var flowMock = new Mock<IFlowClient>();
165+
166+
flowMock.Setup(x => x.TryLoginAsync(
167+
It.IsAny<LoginRequest>(),
168+
It.IsAny<UAuthSubmitMode>(),
169+
It.IsAny<string>()))
170+
.ReturnsAsync(new TryLoginResult { Success = true });
171+
172+
var clientMock = new Mock<IUAuthClient>();
173+
clientMock.Setup(x => x.Flows).Returns(flowMock.Object);
174+
175+
var invoked = false;
176+
177+
ctx.Services.AddSingleton(clientMock.Object);
178+
ctx.Services.AddSingleton(Mock.Of<IDeviceIdProvider>());
179+
ctx.Services.AddSingleton(Mock.Of<IHubCredentialResolver>());
180+
ctx.Services.AddSingleton(Mock.Of<IHubFlowReader>());
181+
ctx.Services.AddSingleton(Mock.Of<IHubCapabilities>());
182+
ctx.Services.AddSingleton<IOptions<UAuthClientOptions>>(Options.Create(new UAuthClientOptions()));
183+
184+
var cut = ctx.Render<UAuthLoginForm>(p => p
185+
.Add(x => x.Identifier, "user")
186+
.Add(x => x.Secret, "pass")
187+
.Add(x => x.OnTryResult, EventCallback.Factory.Create<IUAuthTryResult>(this, _ => invoked = true)));
188+
189+
await cut.Instance.SubmitAsync();
190+
191+
invoked.Should().BeTrue();
192+
}
193+
194+
[Fact]
195+
public void Should_Throw_When_Pkce_Not_Supported()
196+
{
197+
using var ctx = new BunitContext();
198+
199+
var capabilities = new Mock<IHubCapabilities>();
200+
capabilities.Setup(x => x.SupportsPkce).Returns(false);
201+
202+
ctx.Services.AddSingleton(capabilities.Object);
203+
ctx.Services.AddSingleton(Mock.Of<IUAuthClient>());
204+
ctx.Services.AddSingleton(Mock.Of<IDeviceIdProvider>());
205+
ctx.Services.AddSingleton(Mock.Of<IHubCredentialResolver>());
206+
ctx.Services.AddSingleton(Mock.Of<IHubFlowReader>());
207+
ctx.Services.AddSingleton<IOptions<UAuthClientOptions>>(Options.Create(new UAuthClientOptions()));
208+
209+
Action act = () => ctx.Render<UAuthLoginForm>(p => p
210+
.Add(x => x.LoginType, UAuthLoginType.Pkce));
211+
212+
act.Should().Throw<InvalidOperationException>();
213+
}
214+
}

tests/CodeBeam.UltimateAuth.Tests.Unit/CodeBeam.UltimateAuth.Tests.Unit.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
</PropertyGroup>
99

1010
<ItemGroup>
11+
<PackageReference Include="bunit" Version="2.6.2" />
1112
<PackageReference Include="coverlet.collector" Version="6.0.4" />
1213
<PackageReference Include="FluentAssertions" Version="8.8.0" />
1314
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="10.0.5" />

0 commit comments

Comments
 (0)