Skip to content

Commit d794d3c

Browse files
committed
Add Tests
1 parent ed5c5ce commit d794d3c

File tree

6 files changed

+304
-0
lines changed

6 files changed

+304
-0
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
using System.Runtime.CompilerServices;
2+
3+
[assembly: InternalsVisibleTo("CodeBeam.UltimateAuth.Tests.Unit")]
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
using CodeBeam.UltimateAuth.Client.Contracts;
2+
using CodeBeam.UltimateAuth.Client.Diagnostics;
3+
using CodeBeam.UltimateAuth.Client.Infrastructure;
4+
using CodeBeam.UltimateAuth.Client.Options;
5+
using CodeBeam.UltimateAuth.Core.Domain;
6+
using CodeBeam.UltimateAuth.Tests.Unit.Fake;
7+
using Microsoft.Extensions.Options;
8+
9+
namespace CodeBeam.UltimateAuth.Tests.Unit.Client
10+
{
11+
public sealed class BlazorServerSessionCoordinatorTests
12+
{
13+
[Fact]
14+
public async Task StartAsync_MarksStarted_AndAutomaticRefresh()
15+
{
16+
var diagnostics = new UAuthClientDiagnostics();
17+
var client = new FakeUAuthClient(RefreshOutcome.NoOp);
18+
var nav = new TestNavigationManager();
19+
20+
var options = Options.Create(new UAuthClientOptions
21+
{
22+
Refresh = { Interval = TimeSpan.FromMilliseconds(10) }
23+
});
24+
25+
var coordinator = new BlazorServerSessionCoordinator(
26+
client,
27+
nav,
28+
options,
29+
diagnostics);
30+
31+
await coordinator.StartAsync();
32+
await Task.Delay(30);
33+
await coordinator.StopAsync();
34+
35+
Assert.Equal(1, diagnostics.StartCount);
36+
Assert.True(diagnostics.AutomaticRefreshCount >= 1);
37+
}
38+
39+
[Fact]
40+
public async Task ReauthRequired_ShouldTerminateAndNavigate()
41+
{
42+
var diagnostics = new UAuthClientDiagnostics();
43+
var client = new FakeUAuthClient(RefreshOutcome.ReauthRequired);
44+
var nav = new TestNavigationManager();
45+
46+
var options = Options.Create(new UAuthClientOptions
47+
{
48+
Refresh = { Interval = TimeSpan.FromMilliseconds(5) },
49+
Reauth =
50+
{
51+
Behavior = ReauthBehavior.RedirectToLogin,
52+
LoginPath = "/login"
53+
}
54+
});
55+
56+
var coordinator = new BlazorServerSessionCoordinator(
57+
client,
58+
nav,
59+
options,
60+
diagnostics);
61+
62+
await coordinator.StartAsync();
63+
await Task.Delay(20);
64+
65+
Assert.True(diagnostics.IsTerminated);
66+
Assert.Equal(CoordinatorTerminationReason.ReauthRequired, diagnostics.TerminationReason);
67+
Assert.Equal("/login", nav.LastNavigatedTo);
68+
}
69+
70+
[Fact]
71+
public async Task StopAsync_ShouldMarkStopped()
72+
{
73+
var diagnostics = new UAuthClientDiagnostics();
74+
var client = new FakeUAuthClient();
75+
var nav = new TestNavigationManager();
76+
77+
var options = Options.Create(new UAuthClientOptions());
78+
79+
var coordinator = new BlazorServerSessionCoordinator(
80+
client,
81+
nav,
82+
options,
83+
diagnostics);
84+
85+
await coordinator.StartAsync();
86+
await coordinator.StopAsync();
87+
88+
Assert.Equal(1, diagnostics.StopCount);
89+
}
90+
}
91+
}
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
using System;
2+
using CodeBeam.UltimateAuth.Client.Contracts;
3+
using CodeBeam.UltimateAuth.Client.Diagnostics;
4+
using Xunit;
5+
6+
namespace CodeBeam.UltimateAuth.Tests.Unit.Client
7+
{
8+
public class ClientDiagnosticsTests
9+
{
10+
[Fact]
11+
public void MarkStarted_ShouldSetStartedAt_AndIncrementCounter()
12+
{
13+
var diagnostics = new UAuthClientDiagnostics();
14+
diagnostics.MarkStarted();
15+
16+
Assert.NotNull(diagnostics.StartedAt);
17+
Assert.Equal(1, diagnostics.StartCount);
18+
Assert.False(diagnostics.IsTerminated);
19+
}
20+
21+
[Fact]
22+
public void MarkStopped_ShouldSetStoppedAt_AndIncrementCounter()
23+
{
24+
var diagnostics = new UAuthClientDiagnostics();
25+
diagnostics.MarkStopped();
26+
27+
Assert.NotNull(diagnostics.StoppedAt);
28+
Assert.Equal(1, diagnostics.StopCount);
29+
}
30+
31+
[Fact]
32+
public void MarkManualRefresh_ShouldIncrementManualAndTotalCounters()
33+
{
34+
var diagnostics = new UAuthClientDiagnostics();
35+
diagnostics.MarkManualRefresh();
36+
37+
Assert.Equal(1, diagnostics.RefreshAttemptCount);
38+
Assert.Equal(1, diagnostics.ManualRefreshCount);
39+
Assert.Equal(0, diagnostics.AutomaticRefreshCount);
40+
}
41+
42+
[Fact]
43+
public void MarkAutomaticRefresh_ShouldIncrementAutomaticAndTotalCounters()
44+
{
45+
var diagnostics = new UAuthClientDiagnostics();
46+
diagnostics.MarkAutomaticRefresh();
47+
48+
Assert.Equal(1, diagnostics.RefreshAttemptCount);
49+
Assert.Equal(1, diagnostics.AutomaticRefreshCount);
50+
Assert.Equal(0, diagnostics.ManualRefreshCount);
51+
}
52+
53+
[Fact]
54+
public void MarkRefreshOutcomes_ShouldIncrementCorrectCounters()
55+
{
56+
var diagnostics = new UAuthClientDiagnostics();
57+
diagnostics.MarkRefreshTouched();
58+
diagnostics.MarkRefreshNoOp();
59+
diagnostics.MarkRefreshReauthRequired();
60+
diagnostics.MarkRefreshUnknown();
61+
62+
Assert.Equal(1, diagnostics.RefreshTouchedCount);
63+
Assert.Equal(1, diagnostics.RefreshNoOpCount);
64+
Assert.Equal(1, diagnostics.RefreshReauthRequiredCount);
65+
Assert.Equal(1, diagnostics.RefreshUnknownCount);
66+
}
67+
68+
[Fact]
69+
public void MarkTerminated_ShouldSetTerminationState_AndIncrementCounter()
70+
{
71+
var diagnostics = new UAuthClientDiagnostics();
72+
diagnostics.MarkTerminated(CoordinatorTerminationReason.ReauthRequired);
73+
74+
Assert.True(diagnostics.IsTerminated);
75+
Assert.Equal(CoordinatorTerminationReason.ReauthRequired, diagnostics.TerminationReason);
76+
Assert.Equal(1, diagnostics.TerminatedCount);
77+
}
78+
79+
[Fact]
80+
public void ChangedEvent_ShouldFire_OnStateChanges()
81+
{
82+
var diagnostics = new UAuthClientDiagnostics();
83+
int changeCount = 0;
84+
85+
diagnostics.Changed += () => changeCount++;
86+
87+
diagnostics.MarkStarted();
88+
diagnostics.MarkManualRefresh();
89+
diagnostics.MarkRefreshTouched();
90+
diagnostics.MarkTerminated(CoordinatorTerminationReason.ReauthRequired);
91+
92+
Assert.Equal(4, changeCount);
93+
}
94+
95+
[Fact]
96+
public void MarkTerminated_ShouldBeIdempotent_ForStateButCountShouldIncrease()
97+
{
98+
var diagnostics = new UAuthClientDiagnostics();
99+
diagnostics.MarkTerminated(CoordinatorTerminationReason.ReauthRequired);
100+
diagnostics.MarkTerminated(CoordinatorTerminationReason.ReauthRequired);
101+
102+
Assert.True(diagnostics.IsTerminated);
103+
Assert.Equal(2, diagnostics.TerminatedCount);
104+
}
105+
}
106+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
using CodeBeam.UltimateAuth.Client.Infrastructure;
2+
using CodeBeam.UltimateAuth.Core.Domain;
3+
using Xunit;
4+
5+
namespace CodeBeam.UltimateAuth.Tests.Unit
6+
{
7+
public sealed class RefreshOutcomeParserTests
8+
{
9+
[Theory]
10+
[InlineData("no-op", RefreshOutcome.NoOp)]
11+
[InlineData("touched", RefreshOutcome.Touched)]
12+
[InlineData("reauth-required", RefreshOutcome.ReauthRequired)]
13+
public void Parse_KnownValues_ReturnsExpectedOutcome(string input, RefreshOutcome expected)
14+
{
15+
var result = RefreshOutcomeParser.Parse(input);
16+
17+
Assert.Equal(expected, result);
18+
}
19+
20+
[Theory]
21+
[InlineData(null)]
22+
[InlineData("")]
23+
[InlineData(" ")]
24+
[InlineData("unknown")]
25+
[InlineData("NO-OP")]
26+
[InlineData("Touched")]
27+
public void Parse_UnknownOrInvalidValues_ReturnsNone(string? input)
28+
{
29+
var result = RefreshOutcomeParser.Parse(input);
30+
31+
Assert.Equal(RefreshOutcome.None, result);
32+
}
33+
}
34+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
using Microsoft.AspNetCore.Components;
2+
3+
namespace CodeBeam.UltimateAuth.Tests.Unit.Fake
4+
{
5+
internal sealed class TestNavigationManager : NavigationManager
6+
{
7+
public string? LastNavigatedTo { get; private set; }
8+
9+
public TestNavigationManager()
10+
{
11+
Initialize("http://localhost/", "http://localhost/");
12+
}
13+
14+
protected override void NavigateToCore(string uri, bool forceLoad)
15+
{
16+
LastNavigatedTo = uri;
17+
}
18+
}
19+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
using CodeBeam.UltimateAuth.Client;
2+
using CodeBeam.UltimateAuth.Client.Contracts;
3+
using CodeBeam.UltimateAuth.Core.Contracts;
4+
using CodeBeam.UltimateAuth.Core.Domain;
5+
6+
namespace CodeBeam.UltimateAuth.Tests.Unit
7+
{
8+
internal sealed class FakeUAuthClient : IUAuthClient
9+
{
10+
private readonly Queue<RefreshOutcome> _outcomes;
11+
12+
public FakeUAuthClient(params RefreshOutcome[] outcomes)
13+
{
14+
_outcomes = new Queue<RefreshOutcome>(outcomes);
15+
}
16+
17+
public Task LoginAsync(LoginRequest request)
18+
{
19+
throw new NotImplementedException();
20+
}
21+
22+
public Task LogoutAsync()
23+
{
24+
throw new NotImplementedException();
25+
}
26+
27+
public Task ReauthAsync()
28+
{
29+
throw new NotImplementedException();
30+
}
31+
32+
public Task<RefreshResult> RefreshAsync(bool isAuto = false)
33+
{
34+
var outcome = _outcomes.Count > 0
35+
? _outcomes.Dequeue()
36+
: RefreshOutcome.None;
37+
38+
return Task.FromResult(new RefreshResult
39+
{
40+
Ok = true,
41+
Outcome = outcome
42+
});
43+
}
44+
45+
public Task<AuthValidationResult> ValidateAsync()
46+
{
47+
throw new NotImplementedException();
48+
}
49+
}
50+
51+
}

0 commit comments

Comments
 (0)