From c86cc6c58158baaf8a7b0d73c87529b90970a5ef Mon Sep 17 00:00:00 2001 From: Elin Fokine Date: Fri, 9 Oct 2026 10:11:44 +0200 Subject: [PATCH 1/5] Upgrade tests from xUnit v2 to xUnit v3 Replace the deprecated xunit package with xunit.v3 and run tests through Microsoft.Testing.Platform. Test projects are executables, coverage uses Microsoft.Testing.Extensions.CodeCoverage, and the GitHub and Azure Pipelines test commands use the new runner. --- .github/workflows/build.yml | 2 +- .github/workflows/test.yml | 2 +- README.md | 2 ++ azure-pipelines.yml | 16 ++++++++++++---- global.json | 3 +++ ...veLogin.Authentication.BankId.Api.Test.csproj | 6 +++--- ....Authentication.BankId.AspNetCore.Test.csproj | 5 +++-- ...thentication.BankId.AzureKeyVault.Test.csproj | 3 ++- ...eLogin.Authentication.BankId.Core.Test.csproj | 5 +++-- ...in.Authentication.BankId.UAParser.Test.csproj | 7 ++----- test/Directory.Build.props | 2 ++ 11 files changed, 34 insertions(+), 19 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c6556094..44762451 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -68,7 +68,7 @@ jobs: releaseOutputFolder: ${{ runner.temp }}/release - name: Dotnet test - run: dotnet test --configuration ${{ env.dotnetBuildConfiguration }} --collect "Code coverage" + run: dotnet test --solution ActiveLogin.Authentication.sln --configuration ${{ env.dotnetBuildConfiguration }} --coverage shell: pwsh - name: Upload packages diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 7e607b80..c4c5f8f1 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -33,5 +33,5 @@ jobs: shell: pwsh - name: Dotnet test - run: dotnet test --configuration ${{ env.dotnetBuildConfiguration }} --collect "Code coverage" + run: dotnet test --solution ActiveLogin.Authentication.sln --configuration ${{ env.dotnetBuildConfiguration }} --coverage shell: pwsh diff --git a/README.md b/README.md index f074d762..57aa6f54 100644 --- a/README.md +++ b/README.md @@ -187,6 +187,8 @@ Run the following command in the root to run all tests: dotnet test ``` +Tests use xUnit.net v3 with Microsoft.Testing.Platform. From the repository root, `dotnet test` is enough. To target one project, use `dotnet test --project path/to/Project.csproj`. + #### Devcontainer and GitHub Codespaces We also support [devcontainer.json](https://code.visualstudio.com/docs/remote/containers#_create-a-devcontainerjson-file) so that you can [build the solution in a container](https://code.visualstudio.com/docs/remote/containers) and use [GitHub Codespaces](https://docs.github.com/en/codespaces/overview). diff --git a/azure-pipelines.yml b/azure-pipelines.yml index e0123a26..5eb4137b 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -31,7 +31,6 @@ stages: variables: pathToBuildProjects: '**/**/*.*sproj' - pathToTestProjects: '**/test/**/*.Test.*sproj' pathToPackProjects: '**/src/**/*.*sproj' pathToNugetPackages: '**/*.nupkg' @@ -78,9 +77,18 @@ stages: - task: DotNetCoreCLI@2 displayName: 'dotnet test' inputs: - command: test - projects: '$(pathToTestProjects)' - arguments: '--configuration $(dotnetBuildConfiguration) --collect "Code coverage"' + command: custom + custom: test + arguments: '--solution ActiveLogin.Authentication.sln --configuration $(dotnetBuildConfiguration) --coverage --report-xunit-trx --results-directory "$(Agent.TempDirectory)/test-results"' + + - task: PublishTestResults@2 + displayName: 'Publish test results' + condition: succeededOrFailed() + inputs: + testResultsFormat: VSTest + testResultsFiles: '$(Agent.TempDirectory)/test-results/**/*.trx' + mergeTestResults: true + failTaskOnFailedTests: true - publish: '$(Build.ArtifactStagingDirectory)' artifact: '$(artifactName)' diff --git a/global.json b/global.json index 37bf7f81..435d0b66 100644 --- a/global.json +++ b/global.json @@ -2,5 +2,8 @@ "sdk": { "version": "10.0.101", "rollForward": "latestFeature" + }, + "test": { + "runner": "Microsoft.Testing.Platform" } } diff --git a/test/ActiveLogin.Authentication.BankId.Api.Test/ActiveLogin.Authentication.BankId.Api.Test.csproj b/test/ActiveLogin.Authentication.BankId.Api.Test/ActiveLogin.Authentication.BankId.Api.Test.csproj index f5e4b566..bf7a6b8a 100644 --- a/test/ActiveLogin.Authentication.BankId.Api.Test/ActiveLogin.Authentication.BankId.Api.Test.csproj +++ b/test/ActiveLogin.Authentication.BankId.Api.Test/ActiveLogin.Authentication.BankId.Api.Test.csproj @@ -6,14 +6,14 @@ + - + all - runtime; build; native; contentfiles; analyzers + runtime; build; native; contentfiles; analyzers; buildtransitive - diff --git a/test/ActiveLogin.Authentication.BankId.AspNetCore.Test/ActiveLogin.Authentication.BankId.AspNetCore.Test.csproj b/test/ActiveLogin.Authentication.BankId.AspNetCore.Test/ActiveLogin.Authentication.BankId.AspNetCore.Test.csproj index 2ea9334f..039ce351 100644 --- a/test/ActiveLogin.Authentication.BankId.AspNetCore.Test/ActiveLogin.Authentication.BankId.AspNetCore.Test.csproj +++ b/test/ActiveLogin.Authentication.BankId.AspNetCore.Test/ActiveLogin.Authentication.BankId.AspNetCore.Test.csproj @@ -11,12 +11,13 @@ + - + all - runtime; build; native; contentfiles; analyzers + runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/test/ActiveLogin.Authentication.BankId.AzureKeyVault.Test/ActiveLogin.Authentication.BankId.AzureKeyVault.Test.csproj b/test/ActiveLogin.Authentication.BankId.AzureKeyVault.Test/ActiveLogin.Authentication.BankId.AzureKeyVault.Test.csproj index fe954c97..db6132c0 100644 --- a/test/ActiveLogin.Authentication.BankId.AzureKeyVault.Test/ActiveLogin.Authentication.BankId.AzureKeyVault.Test.csproj +++ b/test/ActiveLogin.Authentication.BankId.AzureKeyVault.Test/ActiveLogin.Authentication.BankId.AzureKeyVault.Test.csproj @@ -5,7 +5,8 @@ - + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/test/ActiveLogin.Authentication.BankId.Core.Test/ActiveLogin.Authentication.BankId.Core.Test.csproj b/test/ActiveLogin.Authentication.BankId.Core.Test/ActiveLogin.Authentication.BankId.Core.Test.csproj index bf8ad775..676be30a 100644 --- a/test/ActiveLogin.Authentication.BankId.Core.Test/ActiveLogin.Authentication.BankId.Core.Test.csproj +++ b/test/ActiveLogin.Authentication.BankId.Core.Test/ActiveLogin.Authentication.BankId.Core.Test.csproj @@ -6,11 +6,12 @@ + - + all - runtime; build; native; contentfiles; analyzers + runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/test/ActiveLogin.Authentication.BankId.UAParser.Test/ActiveLogin.Authentication.BankId.UAParser.Test.csproj b/test/ActiveLogin.Authentication.BankId.UAParser.Test/ActiveLogin.Authentication.BankId.UAParser.Test.csproj index 3e8f6680..6bafaa9a 100644 --- a/test/ActiveLogin.Authentication.BankId.UAParser.Test/ActiveLogin.Authentication.BankId.UAParser.Test.csproj +++ b/test/ActiveLogin.Authentication.BankId.UAParser.Test/ActiveLogin.Authentication.BankId.UAParser.Test.csproj @@ -6,16 +6,13 @@ + - + all runtime; build; native; contentfiles; analyzers; buildtransitive - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - diff --git a/test/Directory.Build.props b/test/Directory.Build.props index ab307410..8e36add5 100644 --- a/test/Directory.Build.props +++ b/test/Directory.Build.props @@ -4,6 +4,8 @@ latest true + + Exe false From 9cbeac57ae449f343c52314b91643109ecbd3462 Mon Sep 17 00:00:00 2001 From: Elin Fokine Date: Fri, 9 Oct 2026 10:24:14 +0200 Subject: [PATCH 2/5] Pass the xUnit cancellation token from async test calls Use TestContext.Current.CancellationToken for HttpClient and ReadAsStringAsync calls so xUnit1051 is satisfied without suppressing the analyzer. --- .../BankIdAppApiClient_Tests.cs | 60 +++++++++---------- .../BankIdVerifyApiClient_Tests.cs | 2 +- .../BankId_UiAuth_Tests.cs | 28 ++++----- .../BankId_UiPayment_Tests.cs | 20 +++---- .../BankId_UiSign_Tests.cs | 20 +++---- 5 files changed, 65 insertions(+), 65 deletions(-) diff --git a/test/ActiveLogin.Authentication.BankId.Api.Test/BankIdAppApiClient_Tests.cs b/test/ActiveLogin.Authentication.BankId.Api.Test/BankIdAppApiClient_Tests.cs index 19462cac..aee4470c 100644 --- a/test/ActiveLogin.Authentication.BankId.Api.Test/BankIdAppApiClient_Tests.cs +++ b/test/ActiveLogin.Authentication.BankId.Api.Test/BankIdAppApiClient_Tests.cs @@ -89,7 +89,7 @@ public async Task AuthAsync_WithEndUserIp__ShouldPostJsonPayload_WithEndUserIp_A // Assert var request = _messageHandlerMock.GetFirstArgumentOfFirstInvocation(); - var contentString = await request.Content.ReadAsStringAsync(); + var contentString = await request.Content.ReadAsStringAsync(TestContext.Current.CancellationToken); JsonTests.AssertProperty(contentString, "endUserIp", "1.1.1.1"); JsonTests.AssertPropertyIsEmptyObject(contentString, "requirement"); @@ -110,7 +110,7 @@ public async Task AuthAsync_WithRequirements__ShouldPostJsonPayload_WithRequirem // Assert var request = _messageHandlerMock.GetFirstArgumentOfFirstInvocation(); - var contentString = await request.Content.ReadAsStringAsync(); + var contentString = await request.Content.ReadAsStringAsync(TestContext.Current.CancellationToken); JsonTests.AssertProperty(contentString, "endUserIp", "1.1.1.1"); JsonTests.AssertSubProperty(contentString, "requirement", "certificatePolicies", new List { "req1", "req2" }); @@ -149,7 +149,7 @@ public async Task AuthAsync_WithAuthRequest__ShouldHaveUserData() //Assert var request = _messageHandlerMock.GetFirstArgumentOfFirstInvocation(); - var contentString = await request.Content.ReadAsStringAsync(); + var contentString = await request.Content.ReadAsStringAsync(TestContext.Current.CancellationToken); JsonTests.AssertProperty(contentString, "endUserIp", "1.1.1.1"); JsonTests.AssertPropertyIsEmptyObject(contentString, "requirement"); @@ -190,7 +190,7 @@ public async Task AuthAsync_WithAuthRequest__ShouldHaveAppDeviceParametersPayloa //Assert var request = _messageHandlerMock.GetFirstArgumentOfFirstInvocation(); - var contentString = await request.Content.ReadAsStringAsync(); + var contentString = await request.Content.ReadAsStringAsync(TestContext.Current.CancellationToken); JsonTests.AssertPropertyIsNull(contentString, "web"); JsonTests.AssertPropertyIsNotNull(contentString, "app"); @@ -232,7 +232,7 @@ public async Task AuthAsync_WithAuthRequest__ShouldHaveWebDeviceParametersPayloa //Assert var request = _messageHandlerMock.GetFirstArgumentOfFirstInvocation(); - var contentString = await request.Content.ReadAsStringAsync(); + var contentString = await request.Content.ReadAsStringAsync(TestContext.Current.CancellationToken); JsonTests.AssertPropertyIsNull(contentString, "app"); JsonTests.AssertPropertyIsNotNull(contentString, "web"); @@ -259,7 +259,7 @@ public async Task AuthAsync_WithAuthRequest__ShouldHaveReturnRisk() //Assert var request = _messageHandlerMock.GetFirstArgumentOfFirstInvocation(); - var contentString = await request.Content.ReadAsStringAsync(); + var contentString = await request.Content.ReadAsStringAsync(TestContext.Current.CancellationToken); JsonTests.AssertProperty(contentString, "endUserIp", "1.1.1.1"); JsonTests.AssertPropertyIsEmptyObject(contentString, "requirement"); @@ -284,7 +284,7 @@ public async Task AuthAsync_WithAuthRequest__ShouldHaveReturnUrl() //Assert var request = _messageHandlerMock.GetFirstArgumentOfFirstInvocation(); - var contentString = await request.Content.ReadAsStringAsync(); + var contentString = await request.Content.ReadAsStringAsync(TestContext.Current.CancellationToken); JsonTests.AssertProperty(contentString, "endUserIp", "1.1.1.1"); JsonTests.AssertPropertyIsEmptyObject(contentString, "requirement"); @@ -329,7 +329,7 @@ await _bankIdAppApiClient.SignAsync(new SignRequest( // Assert var request = _messageHandlerMock.GetFirstArgumentOfFirstInvocation(); - var contentString = await request.Content.ReadAsStringAsync(); + var contentString = await request.Content.ReadAsStringAsync(TestContext.Current.CancellationToken); JsonTests.AssertProperty(contentString, "endUserIp", "1.1.1.1"); JsonTests.AssertPropertyIsEmptyObject(contentString, "requirement"); @@ -356,7 +356,7 @@ public async Task SignAsync_WithEndUserIp__ShouldPostJsonPayload_WithEndUserIp_A // Assert var request = _messageHandlerMock.GetFirstArgumentOfFirstInvocation(); - var contentString = await request.Content.ReadAsStringAsync(); + var contentString = await request.Content.ReadAsStringAsync(TestContext.Current.CancellationToken); JsonTests.AssertProperty(contentString, "endUserIp", "1.1.1.1"); JsonTests.AssertPropertyIsEmptyObject(contentString, "requirement"); @@ -379,7 +379,7 @@ public async Task SignAsync_WithEndUserIp__ShouldPostJsonPayload_WithEndUserIp_A // Assert var request = _messageHandlerMock.GetFirstArgumentOfFirstInvocation(); - var contentString = await request.Content.ReadAsStringAsync(); + var contentString = await request.Content.ReadAsStringAsync(TestContext.Current.CancellationToken); JsonTests.AssertProperty(contentString, "endUserIp", "1.1.1.1"); JsonTests.AssertPropertyIsEmptyObject(contentString, "requirement"); @@ -402,7 +402,7 @@ public async Task SignAsync_WithUserNonVisibleData__ShouldPostJsonPayload_WithUs // Assert var request = _messageHandlerMock.GetFirstArgumentOfFirstInvocation(); - var contentString = await request.Content.ReadAsStringAsync(); + var contentString = await request.Content.ReadAsStringAsync(TestContext.Current.CancellationToken); JsonTests.AssertProperty(contentString, "endUserIp", "1.1.1.1"); JsonTests.AssertPropertyIsEmptyObject(contentString, "requirement"); @@ -427,7 +427,7 @@ public async Task SignAsync_WithRequirements__ShouldPostJsonPayload_WithRequirem // Assert var request = _messageHandlerMock.GetFirstArgumentOfFirstInvocation(); - var contentString = await request.Content.ReadAsStringAsync(); + var contentString = await request.Content.ReadAsStringAsync(TestContext.Current.CancellationToken); JsonTests.AssertProperty(contentString, "endUserIp", "1.1.1.1"); JsonTests.AssertSubProperty(contentString, "requirement", "certificatePolicies", new List { "req1", "req2" }); @@ -487,7 +487,7 @@ public async Task SignAsync_WithAuthRequest__ShouldHaveAppDeviceParametersPayloa //Assert var request = _messageHandlerMock.GetFirstArgumentOfFirstInvocation(); - var contentString = await request.Content.ReadAsStringAsync(); + var contentString = await request.Content.ReadAsStringAsync(TestContext.Current.CancellationToken); JsonTests.AssertPropertyIsNull(contentString, "web"); JsonTests.AssertPropertyIsNotNull(contentString, "app"); @@ -529,7 +529,7 @@ public async Task SignAsync_WithAuthRequest__ShouldHaveWebDeviceParametersPayloa //Assert var request = _messageHandlerMock.GetFirstArgumentOfFirstInvocation(); - var contentString = await request.Content.ReadAsStringAsync(); + var contentString = await request.Content.ReadAsStringAsync(TestContext.Current.CancellationToken); JsonTests.AssertPropertyIsNull(contentString, "app"); JsonTests.AssertPropertyIsNotNull(contentString, "web"); @@ -578,7 +578,7 @@ await _bankIdAppApiClient.PaymentAsync(new PaymentRequest( // Assert var request = _messageHandlerMock.GetFirstArgumentOfFirstInvocation(); - var contentString = await request.Content.ReadAsStringAsync(); + var contentString = await request.Content.ReadAsStringAsync(TestContext.Current.CancellationToken); JsonTests.AssertProperty(contentString, "endUserIp", "1.1.1.1"); JsonTests.AssertPropertyIsEmptyObject(contentString, "requirement"); @@ -606,7 +606,7 @@ public async Task PaymentAsync_WithEndUserIp__ShouldPostJsonPayload_WithEndUserI // Assert var request = _messageHandlerMock.GetFirstArgumentOfFirstInvocation(); - var contentString = await request.Content.ReadAsStringAsync(); + var contentString = await request.Content.ReadAsStringAsync(TestContext.Current.CancellationToken); JsonTests.AssertProperty(contentString, "endUserIp", "1.1.1.1"); JsonTests.AssertSubProperty(contentString, "userVisibleTransaction", "transactionType", "npa"); @@ -630,7 +630,7 @@ public async Task PaymentAsync_WithEndUserIp__ShouldPostJsonPayload_WithEndUserI // Assert var request = _messageHandlerMock.GetFirstArgumentOfFirstInvocation(); - var contentString = await request.Content.ReadAsStringAsync(); + var contentString = await request.Content.ReadAsStringAsync(TestContext.Current.CancellationToken); JsonTests.AssertProperty(contentString, "endUserIp", "1.1.1.1"); JsonTests.AssertSubProperty(contentString, "userVisibleTransaction", "transactionType", "npa"); @@ -655,7 +655,7 @@ public async Task PaymentAsync_WithUserNonVisibleData__ShouldPostJsonPayload_Wit // Assert var request = _messageHandlerMock.GetFirstArgumentOfFirstInvocation(); - var contentString = await request.Content.ReadAsStringAsync(); + var contentString = await request.Content.ReadAsStringAsync(TestContext.Current.CancellationToken); JsonTests.AssertProperty(contentString, "endUserIp", "1.1.1.1"); JsonTests.AssertPropertyIsEmptyObject(contentString, "requirement"); @@ -682,7 +682,7 @@ public async Task PaymentAsync_WithRequirements__ShouldPostJsonPayload_WithRequi // Assert var request = _messageHandlerMock.GetFirstArgumentOfFirstInvocation(); - var contentString = await request.Content.ReadAsStringAsync(); + var contentString = await request.Content.ReadAsStringAsync(TestContext.Current.CancellationToken); JsonTests.AssertProperty(contentString, "endUserIp", "1.1.1.1"); JsonTests.AssertSubProperty(contentString, "userVisibleTransaction", "transactionType", "npa"); @@ -741,7 +741,7 @@ public async Task PaymentAsync_WithPaymentRequest__ShouldHaveWebDeviceParameters //Assert var request = _messageHandlerMock.GetFirstArgumentOfFirstInvocation(); - var contentString = await request.Content.ReadAsStringAsync(); + var contentString = await request.Content.ReadAsStringAsync(TestContext.Current.CancellationToken); JsonTests.AssertPropertyIsNull(contentString, "app"); JsonTests.AssertPropertyIsNotNull(contentString, "web"); @@ -784,7 +784,7 @@ public async Task PhoneAuthAsync_WithPersonalNumberAndCallInitiator__ShouldPostJ // Assert var request = _messageHandlerMock.GetFirstArgumentOfFirstInvocation(); - var contentString = await request.Content.ReadAsStringAsync(); + var contentString = await request.Content.ReadAsStringAsync(TestContext.Current.CancellationToken); JsonTests.AssertProperty(contentString, "personalNumber", "201801012392"); JsonTests.AssertProperty(contentString, "callInitiator", "user"); @@ -808,7 +808,7 @@ await _bankIdAppApiClient.PhoneAuthAsync(new PhoneAuthRequest("201801012392", Ca // Assert var request = _messageHandlerMock.GetFirstArgumentOfFirstInvocation(); - var contentString = await request.Content.ReadAsStringAsync(); + var contentString = await request.Content.ReadAsStringAsync(TestContext.Current.CancellationToken); JsonTests.AssertProperty(contentString, "personalNumber", "201801012392"); JsonTests.AssertProperty(contentString, "callInitiator", "user"); @@ -844,7 +844,7 @@ await _bankIdAppApiClient.PhoneAuthAsync(new PhoneAuthRequest("201801012392", Ca //Assert var request = _messageHandlerMock.GetFirstArgumentOfFirstInvocation(); - var contentString = await request.Content.ReadAsStringAsync(); + var contentString = await request.Content.ReadAsStringAsync(TestContext.Current.CancellationToken); JsonTests.AssertProperty(contentString, "personalNumber", "201801012392"); JsonTests.AssertProperty(contentString, "callInitiator", "user"); @@ -897,7 +897,7 @@ await _bankIdAppApiClient.PhoneSignAsync(new PhoneSignRequest( // Assert var request = _messageHandlerMock.GetFirstArgumentOfFirstInvocation(); - var contentString = await request.Content.ReadAsStringAsync(); + var contentString = await request.Content.ReadAsStringAsync(TestContext.Current.CancellationToken); JsonTests.AssertProperty(contentString, "personalNumber", "201801012392"); JsonTests.AssertProperty(contentString, "callInitiator", "user"); @@ -927,7 +927,7 @@ await _bankIdAppApiClient.PhoneSignAsync(new PhoneSignRequest("201801012392", Ca // Assert var request = _messageHandlerMock.GetFirstArgumentOfFirstInvocation(); - var contentString = await request.Content.ReadAsStringAsync(); + var contentString = await request.Content.ReadAsStringAsync(TestContext.Current.CancellationToken); JsonTests.AssertProperty(contentString, "personalNumber", "201801012392"); JsonTests.AssertProperty(contentString, "callInitiator", "user"); @@ -953,7 +953,7 @@ await _bankIdAppApiClient.PhoneSignAsync(new PhoneSignRequest("201801012392", Ca // Assert var request = _messageHandlerMock.GetFirstArgumentOfFirstInvocation(); - var contentString = await request.Content.ReadAsStringAsync(); + var contentString = await request.Content.ReadAsStringAsync(TestContext.Current.CancellationToken); JsonTests.AssertProperty(contentString, "personalNumber", "201801012392"); JsonTests.AssertProperty(contentString, "callInitiator", "user"); @@ -979,7 +979,7 @@ await _bankIdAppApiClient.PhoneSignAsync(new PhoneSignRequest("201801012392", Ca // Assert var request = _messageHandlerMock.GetFirstArgumentOfFirstInvocation(); - var contentString = await request.Content.ReadAsStringAsync(); + var contentString = await request.Content.ReadAsStringAsync(TestContext.Current.CancellationToken); JsonTests.AssertProperty(contentString, "personalNumber", "201801012392"); JsonTests.AssertProperty(contentString, "callInitiator", "user"); @@ -1008,7 +1008,7 @@ await _bankIdAppApiClient.PhoneSignAsync(new PhoneSignRequest("201801012392", Ca // Assert var request = _messageHandlerMock.GetFirstArgumentOfFirstInvocation(); - var contentString = await request.Content.ReadAsStringAsync(); + var contentString = await request.Content.ReadAsStringAsync(TestContext.Current.CancellationToken); JsonTests.AssertProperty(contentString, "personalNumber", "201801012392"); JsonTests.AssertProperty(contentString, "callInitiator", "user"); @@ -1071,7 +1071,7 @@ public async Task CollectAsync_WithOrderRef__ShouldPostJsonPayload_WithOrderRef( // Assert var request = _messageHandlerMock.GetFirstArgumentOfFirstInvocation(); - var contentString = await request.Content.ReadAsStringAsync(); + var contentString = await request.Content.ReadAsStringAsync(TestContext.Current.CancellationToken); JsonTests.AssertProperty(contentString, "orderRef", "abc123"); JsonTests.AssertOnlyProperties(contentString, new[] @@ -1250,7 +1250,7 @@ public async Task CancelAsync_WithOrderRef__ShouldPostJsonPayload_WithOrderRef() // Assert var request = _messageHandlerMock.GetFirstArgumentOfFirstInvocation(); - var contentString = await request.Content.ReadAsStringAsync(); + var contentString = await request.Content.ReadAsStringAsync(TestContext.Current.CancellationToken); JsonTests.AssertProperty(contentString, "orderRef", "abc123"); JsonTests.AssertOnlyProperties(contentString, new[] diff --git a/test/ActiveLogin.Authentication.BankId.Api.Test/BankIdVerifyApiClient_Tests.cs b/test/ActiveLogin.Authentication.BankId.Api.Test/BankIdVerifyApiClient_Tests.cs index 1c2c5808..80fa2efc 100644 --- a/test/ActiveLogin.Authentication.BankId.Api.Test/BankIdVerifyApiClient_Tests.cs +++ b/test/ActiveLogin.Authentication.BankId.Api.Test/BankIdVerifyApiClient_Tests.cs @@ -72,7 +72,7 @@ public async Task VerifyAsync_WithVerifyRequest__ShouldPostToBankIdVerify_WithJs Assert.Single(_messageHandlerMock.Invocations); var request = _messageHandlerMock.GetFirstArgumentOfFirstInvocation(); Assert.NotNull(request); - var contentString = await request.Content.ReadAsStringAsync(); + var contentString = await request.Content.ReadAsStringAsync(TestContext.Current.CancellationToken); Assert.Equal(HttpMethod.Post, request.Method); Assert.Equal(new Uri("https://bankid/verify"), request.RequestUri); diff --git a/test/ActiveLogin.Authentication.BankId.AspNetCore.Test/BankId_UiAuth_Tests.cs b/test/ActiveLogin.Authentication.BankId.AspNetCore.Test/BankId_UiAuth_Tests.cs index e93ff515..ed7d0fdf 100644 --- a/test/ActiveLogin.Authentication.BankId.AspNetCore.Test/BankId_UiAuth_Tests.cs +++ b/test/ActiveLogin.Authentication.BankId.AspNetCore.Test/BankId_UiAuth_Tests.cs @@ -80,7 +80,7 @@ public async Task BankIdUiAuthController_Returns_404_If_BankId_Is_Not_Registered using var client = server.CreateClient(); // Act - var transaction = await client.GetAsync("/ActiveLogin/BankId/Auth"); + var transaction = await client.GetAsync("/ActiveLogin/BankId/Auth", TestContext.Current.CancellationToken); // Assert Assert.Equal(HttpStatusCode.NotFound, transaction.StatusCode); @@ -94,7 +94,7 @@ public async Task BankIdUiAuthApiController_Returns_404_If_BankId_Is_Not_Registe using var client = server.CreateClient(); // Act - var transaction = await client.PostAsync("/ActiveLogin/BankId/Auth/Api/Initialize", null); + var transaction = await client.PostAsync("/ActiveLogin/BankId/Auth/Api/Initialize", null, TestContext.Current.CancellationToken); // Assert Assert.Equal(HttpStatusCode.NotFound, transaction.StatusCode); @@ -118,7 +118,7 @@ public async Task Challenge_Redirects_To_Login() })).CreateClient(); // Act - var transaction = await client.GetAsync("/"); + var transaction = await client.GetAsync("/", TestContext.Current.CancellationToken); // Assert Assert.Equal(HttpStatusCode.Redirect, transaction.StatusCode); @@ -147,7 +147,7 @@ public async Task Challenge_Redirects_To_Login_Respecting_RouteOptions_Lowercase }).CreateClient(); // Act - var transaction = await client.GetAsync("/"); + var transaction = await client.GetAsync("/", TestContext.Current.CancellationToken); // Assert Assert.Equal(HttpStatusCode.Redirect, transaction.StatusCode); @@ -192,7 +192,7 @@ await context.ChallengeAsync( }).CreateClient(); // Act - var transaction = await client.GetAsync("/PathBase"); + var transaction = await client.GetAsync("/PathBase", TestContext.Current.CancellationToken); // Assert Assert.Equal(HttpStatusCode.Redirect, transaction.StatusCode); @@ -276,7 +276,7 @@ public async Task Init_Returns_Ui_With_Resolved_Cancel_Url() // Assert Assert.Equal(HttpStatusCode.OK, transaction.StatusCode); - var transactionContent = await transaction.Content.ReadAsStringAsync(); + var transactionContent = await transaction.Content.ReadAsStringAsync(TestContext.Current.CancellationToken); Assert.Equal("/cru", GetInlineJsonValue(transactionContent, "cancelReturnUrl")); } @@ -309,7 +309,7 @@ public async Task Init_Returns_Ui_With_Script() // Assert Assert.Equal(HttpStatusCode.OK, transaction.StatusCode); - var transactionContent = await transaction.Content.ReadAsStringAsync(); + var transactionContent = await transaction.Content.ReadAsStringAsync(TestContext.Current.CancellationToken); var document = await HtmlDocumentHelper.FromContent(transactionContent); Assert.NotNull(document.GetElement("div.activelogin-bankid-ui--wrapper")); @@ -395,7 +395,7 @@ public async Task AutoLaunch_Sets_Correct_RedirectUri() // Assert Assert.Equal(HttpStatusCode.OK, initializeTransaction.StatusCode); - var responseContent = await initializeTransaction.Content.ReadAsStringAsync(); + var responseContent = await initializeTransaction.Content.ReadAsStringAsync(TestContext.Current.CancellationToken); var responseObject = JsonConvert.DeserializeAnonymousType(responseContent, new { RedirectUri = "", OrderRef = "", IsAutoLaunch = false }); Assert.True(responseObject.IsAutoLaunch); @@ -451,7 +451,7 @@ public async Task Api_Always_Returns_CamelCase_Json_For_Http200Ok() // Assert Assert.Equal(HttpStatusCode.OK, initializeTransaction.StatusCode); - var responseContent = await initializeTransaction.Content.ReadAsStringAsync(); + var responseContent = await initializeTransaction.Content.ReadAsStringAsync(TestContext.Current.CancellationToken); Assert.Contains("redirectUri", responseContent); Assert.Contains("orderRef", responseContent); Assert.Contains("isAutoLaunch", responseContent); @@ -497,7 +497,7 @@ public async Task Api_Always_Returns_CamelCase_Json_For_Http400BadRequest() // Assert Assert.Equal(HttpStatusCode.BadRequest, initializeTransaction.StatusCode); - var responseContent = await initializeTransaction.Content.ReadAsStringAsync(); + var responseContent = await initializeTransaction.Content.ReadAsStringAsync(TestContext.Current.CancellationToken); Assert.Contains("title", responseContent); Assert.Contains("type", responseContent); Assert.Contains("errors", responseContent); @@ -540,7 +540,7 @@ public async Task Cancel_Calls_CancelApi() var loginRequest = CreateRequestWithFakeStateAndUiOptionsCookie(server, "/ActiveLogin/BankId/Auth?returnUrl=%2F"); var loginResponse = await loginRequest.GetAsync(); var loginCookies = loginResponse.Headers.GetValues("set-cookie"); - var loginContent = await loginResponse.Content.ReadAsStringAsync(); + var loginContent = await loginResponse.Content.ReadAsStringAsync(TestContext.Current.CancellationToken); var csrfToken = GetRequestVerificationToken(loginContent); // Arrange acting request @@ -553,8 +553,8 @@ public async Task Cancel_Calls_CancelApi() // Act var client = server.CreateClient(); var initializeTransaction = - await client.PostAsync("/ActiveLogin/BankId/Auth/Api/Initialize", initializeRequest); - var initializeResponseContent = await initializeTransaction.Content.ReadAsStringAsync(); + await client.PostAsync("/ActiveLogin/BankId/Auth/Api/Initialize", initializeRequest, TestContext.Current.CancellationToken); + var initializeResponseContent = await initializeTransaction.Content.ReadAsStringAsync(TestContext.Current.CancellationToken); var initializeObject = JsonConvert.DeserializeAnonymousType(initializeResponseContent, new { RedirectUri = "", OrderRef = "", IsAutoLaunch = false }); @@ -568,7 +568,7 @@ public async Task Cancel_Calls_CancelApi() cancelRequest.Headers.Add("RequestVerificationToken", csrfToken); // Act - var cancelTransaction = await client.PostAsync("/ActiveLogin/BankId/Auth/Api/Cancel", cancelRequest); + var cancelTransaction = await client.PostAsync("/ActiveLogin/BankId/Auth/Api/Cancel", cancelRequest, TestContext.Current.CancellationToken); // Assert Assert.Equal(HttpStatusCode.OK, cancelTransaction.StatusCode); diff --git a/test/ActiveLogin.Authentication.BankId.AspNetCore.Test/BankId_UiPayment_Tests.cs b/test/ActiveLogin.Authentication.BankId.AspNetCore.Test/BankId_UiPayment_Tests.cs index db8db479..fa13920e 100644 --- a/test/ActiveLogin.Authentication.BankId.AspNetCore.Test/BankId_UiPayment_Tests.cs +++ b/test/ActiveLogin.Authentication.BankId.AspNetCore.Test/BankId_UiPayment_Tests.cs @@ -92,7 +92,7 @@ public async Task BankIdUiPaymentController_Returns_404_If_BankId_Is_Not_Registe using var client = server.CreateClient(); // Act - var transaction = await client.GetAsync("/ActiveLogin/BankId/Payment"); + var transaction = await client.GetAsync("/ActiveLogin/BankId/Payment", TestContext.Current.CancellationToken); // Assert Assert.Equal(HttpStatusCode.NotFound, transaction.StatusCode); @@ -106,7 +106,7 @@ public async Task BankIdUiPaymentApiController_Returns_404_If_BankId_Is_Not_Regi using var client = server.CreateClient(); // Act - var transaction = await client.PostAsync("/ActiveLogin/BankId/Payment/Api/Initialize", null); + var transaction = await client.PostAsync("/ActiveLogin/BankId/Payment/Api/Initialize", null, TestContext.Current.CancellationToken); // Assert Assert.Equal(HttpStatusCode.NotFound, transaction.StatusCode); @@ -131,7 +131,7 @@ public async Task InitiatePayment_Redirects_To_Payment() })).CreateClient(); // Act - var transaction = await client.GetAsync("/"); + var transaction = await client.GetAsync("/", TestContext.Current.CancellationToken); // Assert Assert.Equal(HttpStatusCode.Redirect, transaction.StatusCode); @@ -161,7 +161,7 @@ public async Task InitiatePayment_Redirects_To_Payment_Respecting_RouteOptions_L }).CreateClient(); // Act - var transaction = await client.GetAsync("/"); + var transaction = await client.GetAsync("/", TestContext.Current.CancellationToken); // Assert Assert.Equal(HttpStatusCode.Redirect, transaction.StatusCode); @@ -199,7 +199,7 @@ public async Task InitiatePaymentAsync_Redirects_To_Payment_Without_Path_Base() }).CreateClient(); // Act - var transaction = await client.GetAsync("/PathBase"); + var transaction = await client.GetAsync("/PathBase", TestContext.Current.CancellationToken); // Assert Assert.Equal(HttpStatusCode.Redirect, transaction.StatusCode); @@ -282,7 +282,7 @@ public async Task PaymentInit_Returns_Ui_With_Resolved_Cancel_Url() // Assert Assert.Equal(HttpStatusCode.OK, transaction.StatusCode); - var transactionContent = await transaction.Content.ReadAsStringAsync(); + var transactionContent = await transaction.Content.ReadAsStringAsync(TestContext.Current.CancellationToken); Assert.Equal("/cru", GetInlineJsonValue(transactionContent, "cancelReturnUrl")); } @@ -315,7 +315,7 @@ public async Task PaymentInit_Returns_Ui_With_Script() // Assert Assert.Equal(HttpStatusCode.OK, transaction.StatusCode); - var transactionContent = await transaction.Content.ReadAsStringAsync(); + var transactionContent = await transaction.Content.ReadAsStringAsync(TestContext.Current.CancellationToken); var document = await HtmlDocumentHelper.FromContent(transactionContent); Assert.NotNull(document.GetElement("div.activelogin-bankid-ui--wrapper")); @@ -397,7 +397,7 @@ public async Task AutoLaunch_Sets_Correct_RedirectUri() // Assert Assert.Equal(HttpStatusCode.OK, initializeTransaction.StatusCode); - var responseContent = await initializeTransaction.Content.ReadAsStringAsync(); + var responseContent = await initializeTransaction.Content.ReadAsStringAsync(TestContext.Current.CancellationToken); var responseObject = JsonConvert.DeserializeAnonymousType(responseContent, new { RedirectUri = "", OrderRef = "", IsAutoLaunch = false }); Assert.True(responseObject.IsAutoLaunch); @@ -456,7 +456,7 @@ public async Task Api_Always_Returns_CamelCase_Json_For_Http200Ok() // Assert Assert.Equal(HttpStatusCode.OK, initializeTransaction.StatusCode); - var responseContent = await initializeTransaction.Content.ReadAsStringAsync(); + var responseContent = await initializeTransaction.Content.ReadAsStringAsync(TestContext.Current.CancellationToken); Assert.Contains("redirectUri", responseContent); Assert.Contains("orderRef", responseContent); Assert.Contains("isAutoLaunch", responseContent); @@ -508,7 +508,7 @@ public async Task Api_Always_Returns_CamelCase_Json_For_Http400BadRequest() // Assert Assert.Equal(HttpStatusCode.BadRequest, initializeTransaction.StatusCode); - var responseContent = await initializeTransaction.Content.ReadAsStringAsync(); + var responseContent = await initializeTransaction.Content.ReadAsStringAsync(TestContext.Current.CancellationToken); Assert.Contains("title", responseContent); Assert.Contains("type", responseContent); Assert.Contains("errors", responseContent); diff --git a/test/ActiveLogin.Authentication.BankId.AspNetCore.Test/BankId_UiSign_Tests.cs b/test/ActiveLogin.Authentication.BankId.AspNetCore.Test/BankId_UiSign_Tests.cs index ec88bc67..1a3a9116 100644 --- a/test/ActiveLogin.Authentication.BankId.AspNetCore.Test/BankId_UiSign_Tests.cs +++ b/test/ActiveLogin.Authentication.BankId.AspNetCore.Test/BankId_UiSign_Tests.cs @@ -89,7 +89,7 @@ public async Task BankIdUiSignController_Returns_404_If_BankId_Is_Not_Registered using var client = server.CreateClient(); // Act - var transaction = await client.GetAsync("/ActiveLogin/BankId/Sign"); + var transaction = await client.GetAsync("/ActiveLogin/BankId/Sign", TestContext.Current.CancellationToken); // Assert Assert.Equal(HttpStatusCode.NotFound, transaction.StatusCode); @@ -103,7 +103,7 @@ public async Task BankIdUiAuthApiController_Returns_404_If_BankId_Is_Not_Registe using var client = server.CreateClient(); // Act - var transaction = await client.PostAsync("/ActiveLogin/BankId/Sign/Api/Initialize", null); + var transaction = await client.PostAsync("/ActiveLogin/BankId/Sign/Api/Initialize", null, TestContext.Current.CancellationToken); // Assert Assert.Equal(HttpStatusCode.NotFound, transaction.StatusCode); @@ -128,7 +128,7 @@ public async Task InitiateSign_Redirects_To_Sign() })).CreateClient(); // Act - var transaction = await client.GetAsync("/"); + var transaction = await client.GetAsync("/", TestContext.Current.CancellationToken); // Assert Assert.Equal(HttpStatusCode.Redirect, transaction.StatusCode); @@ -158,7 +158,7 @@ public async Task InitiateSign_Redirects_To_Sign_Respecting_RouteOptions_Lowerca }).CreateClient(); // Act - var transaction = await client.GetAsync("/"); + var transaction = await client.GetAsync("/", TestContext.Current.CancellationToken); // Assert Assert.Equal(HttpStatusCode.Redirect, transaction.StatusCode); @@ -196,7 +196,7 @@ public async Task InitiateSignAsync_Redirects_To_Sign_Without_Path_Base() }).CreateClient(); // Act - var transaction = await client.GetAsync("/PathBase"); + var transaction = await client.GetAsync("/PathBase", TestContext.Current.CancellationToken); // Assert Assert.Equal(HttpStatusCode.Redirect, transaction.StatusCode); @@ -279,7 +279,7 @@ public async Task SignInit_Returns_Ui_With_Resolved_Cancel_Url() // Assert Assert.Equal(HttpStatusCode.OK, transaction.StatusCode); - var transactionContent = await transaction.Content.ReadAsStringAsync(); + var transactionContent = await transaction.Content.ReadAsStringAsync(TestContext.Current.CancellationToken); Assert.Equal("/cru", GetInlineJsonValue(transactionContent, "cancelReturnUrl")); } @@ -312,7 +312,7 @@ public async Task SignInit_Returns_Ui_With_Script() // Assert Assert.Equal(HttpStatusCode.OK, transaction.StatusCode); - var transactionContent = await transaction.Content.ReadAsStringAsync(); + var transactionContent = await transaction.Content.ReadAsStringAsync(TestContext.Current.CancellationToken); var document = await HtmlDocumentHelper.FromContent(transactionContent); Assert.NotNull(document.GetElement("div.activelogin-bankid-ui--wrapper")); @@ -394,7 +394,7 @@ public async Task AutoLaunch_Sets_Correct_RedirectUri() // Assert Assert.Equal(HttpStatusCode.OK, initializeTransaction.StatusCode); - var responseContent = await initializeTransaction.Content.ReadAsStringAsync(); + var responseContent = await initializeTransaction.Content.ReadAsStringAsync(TestContext.Current.CancellationToken); var responseObject = JsonConvert.DeserializeAnonymousType(responseContent, new { RedirectUri = "", OrderRef = "", IsAutoLaunch = false }); Assert.True(responseObject.IsAutoLaunch); @@ -453,7 +453,7 @@ public async Task Api_Always_Returns_CamelCase_Json_For_Http200Ok() // Assert Assert.Equal(HttpStatusCode.OK, initializeTransaction.StatusCode); - var responseContent = await initializeTransaction.Content.ReadAsStringAsync(); + var responseContent = await initializeTransaction.Content.ReadAsStringAsync(TestContext.Current.CancellationToken); Assert.Contains("redirectUri", responseContent); Assert.Contains("orderRef", responseContent); Assert.Contains("isAutoLaunch", responseContent); @@ -505,7 +505,7 @@ public async Task Api_Always_Returns_CamelCase_Json_For_Http400BadRequest() // Assert Assert.Equal(HttpStatusCode.BadRequest, initializeTransaction.StatusCode); - var responseContent = await initializeTransaction.Content.ReadAsStringAsync(); + var responseContent = await initializeTransaction.Content.ReadAsStringAsync(TestContext.Current.CancellationToken); Assert.Contains("title", responseContent); Assert.Contains("type", responseContent); Assert.Contains("errors", responseContent); From 4b3b71c53a88c880e4a9235786bf33d3dedfe913 Mon Sep 17 00:00:00 2001 From: Elin Fokine Date: Fri, 9 Oct 2026 10:39:56 +0200 Subject: [PATCH 3/5] Compile TypeScript before collecting static web assets Run the TypeScript 7 compiler before static web asset discovery so a rebuild does not fail when the generated activelogin-main.js has been deleted. --- ...tiveLogin.Authentication.BankId.AspNetCore.csproj | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/ActiveLogin.Authentication.BankId.AspNetCore/ActiveLogin.Authentication.BankId.AspNetCore.csproj b/src/ActiveLogin.Authentication.BankId.AspNetCore/ActiveLogin.Authentication.BankId.AspNetCore.csproj index 63ebe22d..9301989b 100644 --- a/src/ActiveLogin.Authentication.BankId.AspNetCore/ActiveLogin.Authentication.BankId.AspNetCore.csproj +++ b/src/ActiveLogin.Authentication.BankId.AspNetCore/ActiveLogin.Authentication.BankId.AspNetCore.csproj @@ -59,12 +59,12 @@ - - - CompileTypeScript; - $(ResolveCurrentProjectStaticWebAssetsInputs) - - + + + + + + wwwroot From 0831c4730453567e05324a7e28f7af90c5f7f1fc Mon Sep 17 00:00:00 2001 From: Elin Fokine Date: Fri, 9 Oct 2026 11:35:30 +0200 Subject: [PATCH 4/5] Publish code coverage from Azure Pipelines after xunit v3 upgrade Microsoft Testing Platform's --coverage flag only produces binary .coverage files, so Azure DevOps had no HTML report to render. - Output coverage as Cobertura via --coverage-output-format cobertura - Add PublishCodeCoverageResults@2 step to publish the results --- azure-pipelines.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 5eb4137b..e082dfd7 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -79,7 +79,13 @@ stages: inputs: command: custom custom: test - arguments: '--solution ActiveLogin.Authentication.sln --configuration $(dotnetBuildConfiguration) --coverage --report-xunit-trx --results-directory "$(Agent.TempDirectory)/test-results"' + --coverage --coverage-output-format cobertura --report-xunit-trx --results-directory "$(Agent.TempDirectory)/test-results"' + + - task: PublishCodeCoverageResults@2 + displayName: 'Publish code coverage' + condition: succeededOrFailed() + inputs: + summaryFileLocation: '$(Agent.TempDirectory)/test-results/**/*.cobertura.xml' - task: PublishTestResults@2 displayName: 'Publish test results' From a7cf78a9a421ab57053a05d927a7be5e9b979d09 Mon Sep 17 00:00:00 2001 From: Elin Fokine Date: Fri, 9 Oct 2026 11:39:29 +0200 Subject: [PATCH 5/5] Fix bug in azure-pipeline.yml --- azure-pipelines.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index e082dfd7..58d8c7ee 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -79,13 +79,13 @@ stages: inputs: command: custom custom: test - --coverage --coverage-output-format cobertura --report-xunit-trx --results-directory "$(Agent.TempDirectory)/test-results"' + arguments: '--solution ActiveLogin.Authentication.sln --configuration $(dotnetBuildConfiguration) --coverage --coverage-output-format cobertura --report-xunit-trx --results-directory "$(Agent.TempDirectory)/test-results"' - - task: PublishCodeCoverageResults@2 - displayName: 'Publish code coverage' - condition: succeededOrFailed() - inputs: - summaryFileLocation: '$(Agent.TempDirectory)/test-results/**/*.cobertura.xml' + - task: PublishCodeCoverageResults@2 + displayName: 'Publish code coverage' + condition: succeededOrFailed() + inputs: + summaryFileLocation: '$(Agent.TempDirectory)/test-results/**/*.cobertura.xml' - task: PublishTestResults@2 displayName: 'Publish test results'