-
-
Notifications
You must be signed in to change notification settings - Fork 117
Dev authorization fakes #151
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 15 commits
Commits
Show all changes
94 commits
Select commit
Hold shift + click to select a range
ebc8530
Created fake helper classes to assist with testing Blazor authenticat…
DarthPedro 16b7585
Added extension methods to add appropriate authentication/authorizati…
DarthPedro f92a850
Added component tests that use AuthorizeView and the BUnit authorizat…
DarthPedro 80baed4
Updated changelog and minor cleanup for SimpleAuthView and test.
DarthPedro 35b9b5c
Added placeholders for AuthenticationStateProvider and IAuthorization…
DarthPedro ffbc120
Merge pull request #1 from egil/dev
DarthPedro 308914a
committing this to be able to switch
DarthPedro f6f4471
Created fake helper classes to assist with testing Blazor authenticat…
DarthPedro f804a1e
Added extension methods to add appropriate authentication/authorizati…
DarthPedro b0931ec
Added component tests that use AuthorizeView and the BUnit authorizat…
DarthPedro 6deb8c5
Updated changelog and minor cleanup for SimpleAuthView and test.
DarthPedro 908d219
Added placeholders for AuthenticationStateProvider and IAuthorization…
DarthPedro 7316fb0
Merge branch 'dev-authorization-fakes' of https://github.com/DarthPed…
DarthPedro 6ef2e83
Added documentation for fake authorization services and how to use them.
DarthPedro a316b3e
Fixed code formatting in documentation.
DarthPedro e753deb
Update docs/site/docs/mocking/mocking-auth.md
DarthPedro bd1dcbb
Update src/bunit.web/TestDoubles/Authorization/FakeAuthenticationStat…
DarthPedro 94e1d77
Update docs/site/docs/mocking/mocking-auth.md
DarthPedro 402b38d
Update src/bunit.web.tests/TestDoubles/Authorization/FakeAuthorizatio…
DarthPedro fa5d230
Update src/bunit.web.tests/TestDoubles/Authorization/LoginDisplay.razor
DarthPedro 9f4b4fe
Update src/bunit.web.tests/TestDoubles/Authorization/LoginDisplayTest.cs
DarthPedro 8defb66
Update src/bunit.web.tests/TestDoubles/Authorization/LoginDisplayTest.cs
DarthPedro b28ad7b
Update src/bunit.web.tests/TestDoubles/Authorization/SimpleAuthView.r…
DarthPedro 45280c6
Update src/bunit.web.tests/TestDoubles/Authorization/LoginDisplayTest.cs
DarthPedro 2f8c99e
Update src/bunit.web.tests/TestDoubles/Authorization/LoginDisplayTest.cs
DarthPedro 94f8035
Merge pull request #3 from egil/dev
DarthPedro 9ed6e40
Merge branch 'dev' of https://github.com/DarthPedro/bUnit into dev
DarthPedro 9bad52b
Created fake helper classes to assist with testing Blazor authenticat…
DarthPedro e49a77e
Added extension methods to add appropriate authentication/authorizati…
DarthPedro 534144c
Added component tests that use AuthorizeView and the BUnit authorizat…
DarthPedro 2e86791
Updated changelog and minor cleanup for SimpleAuthView and test.
DarthPedro 084b0f1
Added placeholders for AuthenticationStateProvider and IAuthorization…
DarthPedro a3929c4
Update src/bunit.web/TestDoubles/Authorization/FakeAuthenticationStat…
DarthPedro c8cf267
Update src/bunit.web.tests/TestDoubles/Authorization/FakeAuthorizatio…
DarthPedro 232efd9
Update src/bunit.web.tests/TestDoubles/Authorization/LoginDisplay.razor
DarthPedro 1d1a577
Update src/bunit.web.tests/TestDoubles/Authorization/LoginDisplayTest.cs
DarthPedro 05799b2
Update src/bunit.web.tests/TestDoubles/Authorization/LoginDisplayTest.cs
DarthPedro d979d30
Update src/bunit.web.tests/TestDoubles/Authorization/SimpleAuthView.r…
DarthPedro cb0442d
Update src/bunit.web.tests/TestDoubles/Authorization/LoginDisplayTest.cs
DarthPedro 4dea2f4
Update src/bunit.web.tests/TestDoubles/Authorization/LoginDisplayTest.cs
DarthPedro 2b6939c
committing merge with dev doc changes
DarthPedro 99bf847
Removed this prefixes from usage in code.
DarthPedro d4eda28
Rename SimpleAuthViewTest to AuthorizationTests to better describe wh…
DarthPedro 086dbc6
Added AuthorizationState enum to encapsulate the states. Changed API …
DarthPedro ecb1f9a
Renamed FakeAuthorizationExtensions.AddAuthorization to AddTestAuthor…
DarthPedro 50306e5
Replaced FakeAuthorizationService.NextResult to be CurrentState with …
DarthPedro 561575c
Added simplifying methods to FakeAuthorizationExtensions to UpdateTes…
DarthPedro 6579e98
Added factory method to simplify creating ClaimsPrincipal when needed.
DarthPedro e9e95d9
Update docs/site/docs/test-doubles/faking-auth.md
DarthPedro c6f69b1
Update docs/site/docs/test-doubles/faking-auth.md
DarthPedro be481cd
Update src/bunit.web/TestDoubles/Authorization/MissingFakeAuthorizati…
DarthPedro 821573e
Fix build failure caused by IList property with a setter.
DarthPedro 82bd35d
Moved SimpleAuthTest to bunit.testassets project. Fixed tests to refe…
DarthPedro 3f6c598
Add an explicit SetAuthorizationState to FakeAuthorizationService.
DarthPedro ffcae94
Hide the CurrentState property because it's an implementation detail.
DarthPedro 11629f6
Made policy scheme name a settable property with a default to TestSch…
DarthPedro 97dd96f
Created an AuthorizationAdaptor to wrap some of the auth services and…
DarthPedro e707b5e
Renamed AuthorizationAdaptor to TestAuthorizationContext and minor cl…
DarthPedro 6ac02d1
Changed Roles properties to be non-nullable in TestAuthorizationConte…
DarthPedro a5f09a3
Renamed TestAuthorizationContext methods to SetAuthorized and SetNotA…
DarthPedro 2e513d2
Update CHANGELOG.md with PR comments
DarthPedro bb9448a
Minor clean ups from PR comments.
DarthPedro 55e34f7
Added check to property setters in FakeIdentity and FakeAuthorization…
DarthPedro cd70c01
Exposed AuthorizeCalls through TestAuthorizationContext for callers t…
DarthPedro 08b6405
Small style tweaks to code, spelling, etc.
egil 295a3b1
Merge branch 'dev' into dev-authorization-fakes
egil a189d58
Added back .Render() to test removed during experiments
egil 06f3faa
Additional simplifications of code, update to changelog
egil b7171ce
Fixed tests and code that broke during refactor
egil 0862a8f
Added empty string check to PolicySchemeName. Removed AuthorizeCalls
DarthPedro a818c2f
Added documentation sample code to the bunit.docs.samples project. Up…
DarthPedro 3e4b04d
Merge branch 'dev' into dev-authorization-fakes
egil ac59ecf
Made roles list in SetAuthorized a params string[] roles, making it e…
DarthPedro c67cfd4
Added TestAuthorizationContext.SetAuthorizationPolicies as way for ca…
DarthPedro e206bf0
Fix up sample build break.
DarthPedro a944488
Added SimpleAuthViewWithPolicy component to validate testing with Aut…
DarthPedro a88b2aa
Added sample code and unit tests for using AuthorizeView with Policy.
DarthPedro 4f5fc66
changed role names, and removed ConfigureAwait calls from test classes.
DarthPedro 10fdc3c
Made CreatePrincipal internal
DarthPedro ed87615
Added SetRoles method, and made the TestAuthorizationContext methods …
DarthPedro 4b518bd
Updated samples to the TestAuthorizationContext api changes.
DarthPedro 26a21ac
Updated docs to match the style of the other pages
egil 92b06e3
Added docs samples
egil 41725b4
Tests (which breaks) for missing or invalid roles and policies
egil 4c65bb1
removed src/bunit.testassets/SampleComponents/SimpleWithJsRuntimeDep.…
egil 2851cdb
Readded SimpleWithJSRuntimeDep.razor
egil 5bfd207
Fix FakeAuthorizationService to validate checks for policies and role…
DarthPedro 7e6081e
Added SetAuthorizing method and state implementation to get Authorize…
DarthPedro 315ea0f
Added TestAuthorizationContext.SetClaims and implementation in servic…
DarthPedro 38c8aef
Clean up from PR comments.
DarthPedro 97953dc
Added negative test for AuthorizeView without defined claims.
DarthPedro 4bb2386
Update docs/samples/components/UserInfo.razor
DarthPedro be8f9dd
Changed code to remove null pointer exception if authorizing state wa…
egil c561fe1
Docs: added authorizing example to tests, fixed spelling and gramma
egil File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,8 +1,132 @@ | ||
| --- | ||
| --- | ||
| uid: mocking-auth | ||
DarthPedro marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| title: Mocking Blazor's Authorization | ||
DarthPedro marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| --- | ||
|
|
||
| # Mocking Blazor's Authorization | ||
|
|
||
| https://github.com/egil/bunit/issues/135 | ||
| https://github.com/egil/bunit/issues/135 | ||
|
|
||
| When testing Blazor components that require authentication and authorization, you need to set up enough of the services and behavior to work with the Blazor AuthorizeView, CascadingAuthenticationState, and AuthorizeRouteView. | ||
|
|
||
| You can use AuthorizeView in a component to show different content based on the user's authentication/authorization state. To set your component up for testing, you can do the following: | ||
|
|
||
| ```c# | ||
DarthPedro marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| @using Microsoft.AspNetCore.Components.Authorization | ||
|
|
||
| <CascadingAuthenticationState> | ||
| <AuthorizeView> | ||
| <Authorized> | ||
| Authorized! | ||
| </Authorized> | ||
| <NotAuthorized> | ||
| Not authorized? | ||
| </NotAuthorized> | ||
| </AuthorizeView> | ||
| </CascadingAuthenticationState> | ||
| ``` | ||
|
|
||
| To easily test this type of component, bUnit has some test services that help. You will need to add these services to your test context before you render and run your tests. | ||
|
|
||
| The following code tests the component with an unauthenticated user. To setup an authenticated user, just call AddAuthorization with no parameters. | ||
|
|
||
| ```c# | ||
| [Fact(DisplayName = "AuthorizeView with unauthenticated user")] | ||
| public void Test001() | ||
| { | ||
| // arrange | ||
| using var ctx = new TestContext(); | ||
| ctx.Services.AddAuthorization(); | ||
|
|
||
| // act | ||
| var cut = ctx.RenderComponent<SimpleAuthView>(); | ||
|
|
||
| // assert | ||
| cut.MarkupMatches("Not authorized?"); | ||
| } | ||
| ``` | ||
|
|
||
| Now we can test with an authenticated and authorized user by calling AddAuthorization with a user name and authorization flag. | ||
|
|
||
| ```c# | ||
| [Fact(DisplayName = "AuthorizeView with authenticated and authorized user")] | ||
| public void Test002() | ||
| { | ||
| // arrange | ||
| using var ctx = new TestContext(); | ||
| ctx.Services.AddAuthorization("TestUser", true); | ||
|
|
||
| // act | ||
| var cut = ctx.RenderComponent<SimpleAuthView>(); | ||
|
|
||
| // assert | ||
| cut.MarkupMatches("Authorized!"); | ||
| } | ||
| ``` | ||
|
|
||
| Finally we can test with an authenticated and unauthorized user in the code below. | ||
|
|
||
| ```c# | ||
| [Fact(DisplayName = "AuthorizeView with authenticated but unauthorized user")] | ||
| public void Test003() | ||
| { | ||
| // arrange | ||
| using var ctx = new TestContext(); | ||
| ctx.Services.AddAuthorization("TestUser", false); | ||
|
|
||
| // act | ||
| var cut = ctx.RenderComponent<SimpleAuthView>(); | ||
|
|
||
| // assert | ||
| cut.MarkupMatches("Not authorized?"); | ||
| } | ||
| ``` | ||
|
|
||
| In addition to using these services with AuthorizeView, you can also inject the services into your component and call them in your C# code. | ||
|
|
||
| ```c# | ||
| @using Microsoft.AspNetCore.Components.WebAssembly.Authentication | ||
| @inject AuthenticationStateProvider AuthenticationStateProvider | ||
|
|
||
| <p>Test Component</p> | ||
|
|
||
| @if (isAuthenticated) | ||
| { | ||
| <p>User: @userName</p> | ||
| } | ||
|
|
||
| @code{ | ||
| bool isAuthenticated = false; | ||
| string userName; | ||
|
|
||
| protected override async Task OnInitializedAsync() | ||
| { | ||
| var state = await AuthenticationStateProvider.GetAuthenticationStateAsync().ConfigureAwait(false); | ||
| if (state != null) | ||
| { | ||
| this.isAuthenticated = state.User.Identity.IsAuthenticated; | ||
| this.userName = state.User.Identity.Name; | ||
| } | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| Then you can write a similar test as the ones above. | ||
|
|
||
| ```c# | ||
| [Fact(DisplayName = "Use AuthenticationStateProvider service with authenticated and authorized user")] | ||
| public void Test004() | ||
| { | ||
| // arrange | ||
| using var ctx = new TestContext(); | ||
| ctx.Services.AddAuthorization("TestUserName", true); | ||
|
|
||
| // act | ||
| var cut = ctx.RenderComponent<TestComponent>(); | ||
|
|
||
| // assert | ||
| Assert.Contains("<p>User: TestUserName</p>", cut.Markup, StringComparison.InvariantCulture); | ||
| } | ||
| ``` | ||
|
|
||
| That is all you need to support authorization and authentication testing in bUnit. | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
62 changes: 62 additions & 0 deletions
62
src/bunit.web.tests/TestDoubles/Authorization/FakeAuthenticationStateProviderTest.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,62 @@ | ||
| using System.Collections.Generic; | ||
| using System.Threading.Tasks; | ||
| using Xunit; | ||
|
|
||
| namespace Bunit.TestDoubles.Authorization | ||
| { | ||
| public class FakeAuthenticationStateProviderTest | ||
| { | ||
| [Fact(DisplayName = "Create authenticated AuthenticationState")] | ||
| public async Task Test001() | ||
| { | ||
| // arrange | ||
| var roles = new List<string> { "User" }; | ||
|
|
||
| // act | ||
| var authProvider = new FakeAuthenticationStateProvider("TestUser", roles); | ||
| var authState = await authProvider.GetAuthenticationStateAsync(); | ||
|
|
||
| // assert | ||
| Assert.NotNull(authState.User); | ||
| Assert.NotNull(authState.User.Identity); | ||
| Assert.Equal("TestUser", authState.User.Identity.Name); | ||
| Assert.True(authState.User.Identity.IsAuthenticated); | ||
| } | ||
|
|
||
| [Fact(DisplayName = "Create unauthenticated AuthenticationState")] | ||
| public async Task Test002() | ||
| { | ||
| // act | ||
| var authProvider = new FakeAuthenticationStateProvider(); | ||
| var authState = await authProvider.GetAuthenticationStateAsync(); | ||
|
|
||
| // assert | ||
| Assert.NotNull(authState.User); | ||
| Assert.NotNull(authState.User.Identity); | ||
| Assert.Null(authState.User.Identity.Name); | ||
| Assert.False(authState.User.Identity.IsAuthenticated); | ||
| } | ||
|
|
||
| [Fact(DisplayName = "Switch AuthenticationState from unauthenticated to authenticated.")] | ||
| public async Task Test003() | ||
| { | ||
| // arrange | ||
| var authProvider = new FakeAuthenticationStateProvider(); | ||
| var stateChangeHandled = false; | ||
| authProvider.AuthenticationStateChanged += e => stateChangeHandled = true; | ||
|
|
||
| var newState = FakeAuthenticationStateProvider.CreateAuthenticationState("NewUser"); | ||
DarthPedro marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| // act | ||
| authProvider.TriggerAuthenticationStateChanged(newState); | ||
| var authState = await authProvider.GetAuthenticationStateAsync(); | ||
|
|
||
| // assert | ||
| Assert.True(stateChangeHandled); | ||
| Assert.NotNull(authState.User); | ||
| Assert.NotNull(authState.User.Identity); | ||
| Assert.Equal("NewUser", authState.User.Identity.Name); | ||
| Assert.True(authState.User.Identity.IsAuthenticated); | ||
| } | ||
| } | ||
| } | ||
89 changes: 89 additions & 0 deletions
89
src/bunit.web.tests/TestDoubles/Authorization/FakeAuthorizationExtensionsTest.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,89 @@ | ||
| using System.Collections.Generic; | ||
| using System.Security.Claims; | ||
| using System.Threading.Tasks; | ||
| using Microsoft.AspNetCore.Authorization; | ||
| using Microsoft.AspNetCore.Components.Authorization; | ||
| using Microsoft.Extensions.DependencyInjection; | ||
| using Xunit; | ||
|
|
||
| namespace Bunit.TestDoubles.Authorization | ||
| { | ||
| public class FakeAuthorizationExtensionsTest | ||
| { | ||
| [Fact(DisplayName = "Register Authorization services with authenticated and authorized user.")] | ||
| public async Task Test001() | ||
| { | ||
| // arrange | ||
| using var sp = new TestServiceProvider(); | ||
| var roles = new List<string> { "User" }; | ||
| var principal = new ClaimsPrincipal( | ||
| new FakePrincipal { Identity = new FakeIdentity { Name = "DarthPedro" }, Roles = roles }); | ||
DarthPedro marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| // act | ||
| sp.AddAuthorization("DarthPedro", true, roles); | ||
DarthPedro marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| var authProvider = sp.GetRequiredService<AuthenticationStateProvider>(); | ||
| var authState = await authProvider.GetAuthenticationStateAsync(); | ||
|
|
||
| var authService = sp.GetRequiredService<IAuthorizationService>(); | ||
| var authResult = await authService.AuthorizeAsync(principal, "testResource", "testPolicy"); | ||
|
|
||
| // assert | ||
| Assert.NotNull(authState.User); | ||
| Assert.NotNull(authState.User.Identity); | ||
| Assert.Equal("DarthPedro", authState.User.Identity.Name); | ||
| Assert.True(authState.User.Identity.IsAuthenticated); | ||
| Assert.True(authResult.Succeeded); | ||
| } | ||
|
|
||
| [Fact(DisplayName = "Register Authorization services with authenticated but unauthorized user.")] | ||
| public async Task Test002() | ||
| { | ||
| // arrange | ||
| using var sp = new TestServiceProvider(); | ||
| var principal = new ClaimsPrincipal( | ||
| new FakePrincipal { Identity = new FakeIdentity { Name = "DarthPedro" } }); | ||
|
|
||
| // act | ||
| sp.AddAuthorization("DarthPedro", false); | ||
|
|
||
| var authProvider = sp.GetRequiredService<AuthenticationStateProvider>(); | ||
| var authState = await authProvider.GetAuthenticationStateAsync(); | ||
|
|
||
| var authService = sp.GetRequiredService<IAuthorizationService>(); | ||
| var authResult = await authService.AuthorizeAsync(principal, "testResource", "testPolicy"); | ||
|
|
||
| // assert | ||
| Assert.NotNull(authState.User); | ||
| Assert.NotNull(authState.User.Identity); | ||
| Assert.Equal("DarthPedro", authState.User.Identity.Name); | ||
| Assert.True(authState.User.Identity.IsAuthenticated); | ||
| Assert.False(authResult.Succeeded); | ||
| } | ||
|
|
||
| [Fact(DisplayName = "Register Authorization services with unauthenticated user.")] | ||
| public async Task Test003() | ||
| { | ||
| // arrange | ||
| using var sp = new TestServiceProvider(); | ||
| var principal = new ClaimsPrincipal( | ||
| new FakePrincipal { Identity = new FakeIdentity { Name = "DarthPedro" } }); | ||
|
|
||
| // act | ||
| sp.AddAuthorization(); | ||
DarthPedro marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| var authProvider = sp.GetRequiredService<AuthenticationStateProvider>(); | ||
| var authState = await authProvider.GetAuthenticationStateAsync(); | ||
|
|
||
| var authService = sp.GetRequiredService<IAuthorizationService>(); | ||
| var authResult = await authService.AuthorizeAsync(principal, "testResource", "testPolicy"); | ||
|
|
||
| // assert | ||
| Assert.NotNull(authState.User); | ||
| Assert.NotNull(authState.User.Identity); | ||
| Assert.Null(authState.User.Identity.Name); | ||
| Assert.False(authState.User.Identity.IsAuthenticated); | ||
| Assert.False(authResult.Succeeded); | ||
| } | ||
| } | ||
| } | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.