diff --git a/.github/workflows/Build_&_Test.yml b/.github/workflows/Build_&_Test.yml
index 256c10b..ecd73fa 100644
--- a/.github/workflows/Build_&_Test.yml
+++ b/.github/workflows/Build_&_Test.yml
@@ -5,7 +5,7 @@
#
# - To turn off auto-generation set:
#
-# [GitHubActions (AutoGenerate = false)]
+# [GithubActionsExtended (AutoGenerate = false)]
#
# - To trigger manual generation invoke:
#
@@ -29,10 +29,12 @@ jobs:
name: ubuntu-latest
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
- uses: actions/setup-dotnet@v4
with:
- dotnet-version: '9'
+ dotnet-version: |
+ 8.0
+ 9.0
+ - uses: actions/checkout@v4
- name: 'Cache: .nuke/temp, ~/.nuget/packages'
uses: actions/cache@v4
with:
diff --git a/.github/workflows/Manual_Nuget_Push.yml b/.github/workflows/Manual_Nuget_Push.yml
index 4299d2a..7878728 100644
--- a/.github/workflows/Manual_Nuget_Push.yml
+++ b/.github/workflows/Manual_Nuget_Push.yml
@@ -5,7 +5,7 @@
#
# - To turn off auto-generation set:
#
-# [GitHubActions (AutoGenerate = false)]
+# [GithubActionsExtended (AutoGenerate = false)]
#
# - To trigger manual generation invoke:
#
@@ -23,10 +23,12 @@ jobs:
name: ubuntu-latest
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
- uses: actions/setup-dotnet@v4
with:
- dotnet-version: '9'
+ dotnet-version: |
+ 8.0
+ 9.0
+ - uses: actions/checkout@v4
- name: 'Cache: .nuke/temp, ~/.nuget/packages'
uses: actions/cache@v4
with:
diff --git a/Package.Build.props b/Package.Build.props
index f24381a..722fc48 100644
--- a/Package.Build.props
+++ b/Package.Build.props
@@ -7,7 +7,7 @@
https://github.com/Hawxy/Fga.Net
https://github.com/Hawxy/Fga.Net
git
- Hawxy 2022-2024
+ Hawxy 2022-2025
true
README.md
diff --git a/build/Build.SetupDotNet.cs b/build/Build.SetupDotNet.cs
new file mode 100644
index 0000000..e53f090
--- /dev/null
+++ b/build/Build.SetupDotNet.cs
@@ -0,0 +1,58 @@
+using System.Collections.Generic;
+using Nuke.Common.CI.GitHubActions;
+using Nuke.Common.CI.GitHubActions.Configuration;
+using Nuke.Common.Execution;
+using Nuke.Common.Utilities;
+
+public class GitHubActionsSetupDotNetStep : GitHubActionsStep
+{
+ public GitHubActionsSetupDotNetStep(string[] versions)
+ {
+ Versions = versions;
+ }
+
+ string[] Versions { get; }
+
+ public override void Write(CustomFileWriter writer)
+ {
+ writer.WriteLine("- uses: actions/setup-dotnet@v4");
+
+ using (writer.Indent())
+ {
+ writer.WriteLine("with:");
+ using (writer.Indent())
+ {
+ writer.WriteLine("dotnet-version: |");
+ using (writer.Indent())
+ {
+ foreach (var version in Versions)
+ {
+ writer.WriteLine(version);
+ }
+ }
+ }
+ }
+ }
+}
+
+public class GithubActionsExtendedAttribute : GitHubActionsAttribute
+{
+ public GithubActionsExtendedAttribute(string name, GitHubActionsImage image, params GitHubActionsImage[] images) : base(name, image, images)
+ {
+ }
+
+ protected override GitHubActionsJob GetJobs(GitHubActionsImage image,
+ IReadOnlyCollection relevantTargets)
+ {
+ var job = base.GetJobs(image, relevantTargets);
+
+ var newSteps = new List(job.Steps);
+ newSteps.Insert(0, new GitHubActionsSetupDotNetStep([
+ "8.0", "9.0"
+ ]));
+
+ job.Steps = newSteps.ToArray();
+
+ return job;
+ }
+}
\ No newline at end of file
diff --git a/build/Build.cs b/build/Build.cs
index 977000b..70be675 100644
--- a/build/Build.cs
+++ b/build/Build.cs
@@ -10,21 +10,19 @@
using static Nuke.Common.Tools.DotNet.DotNetTasks;
[ShutdownDotNetAfterServerBuild]
-[GitHubActions(
+[GithubActionsExtended(
"Build & Test",
GitHubActionsImage.UbuntuLatest,
- AutoGenerate = false,
- OnPushBranches = new []{ "main" },
- OnPullRequestBranches = new []{ "main" },
- InvokedTargets = new[] { nameof(Test) },
- ImportSecrets = new []{ nameof(FgaStoreId), nameof(FgaClientId), nameof(FgaClientSecret) })]
-[GitHubActions(
+ OnPushBranches = ["main"],
+ OnPullRequestBranches = ["main"],
+ InvokedTargets = [nameof(Test)],
+ ImportSecrets = [nameof(FgaStoreId), nameof(FgaClientId), nameof(FgaClientSecret)])]
+[GithubActionsExtended(
"Manual Nuget Push",
GitHubActionsImage.UbuntuLatest,
- AutoGenerate = false,
- On = new[] { GitHubActionsTrigger.WorkflowDispatch },
- InvokedTargets = new[] { nameof(NugetPush) },
- ImportSecrets = new[] { nameof(NugetApiKey) })]
+ On = [GitHubActionsTrigger.WorkflowDispatch],
+ InvokedTargets = [nameof(NugetPush)],
+ ImportSecrets = [nameof(NugetApiKey)])]
class Build : NukeBuild
{
/// Support plugins are available for:
diff --git a/build/_build.csproj b/build/_build.csproj
index 446c9fd..96c9f80 100644
--- a/build/_build.csproj
+++ b/build/_build.csproj
@@ -2,7 +2,7 @@
Exe
- net8.0
+ net9.0
CS0649;CS0169
..
@@ -11,7 +11,7 @@
-
+
diff --git a/tests/Fga.Net.Tests/Client/EndpointTests.cs b/tests/Fga.Net.Tests/Client/EndpointTests.cs
index ebe6384..6434cff 100644
--- a/tests/Fga.Net.Tests/Client/EndpointTests.cs
+++ b/tests/Fga.Net.Tests/Client/EndpointTests.cs
@@ -1,111 +1,38 @@
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
-using Alba;
-using Fga.Net.DependencyInjection.Configuration;
+using Fga.Net.DependencyInjection.Configuration;
+using FluentAssertions;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using OpenFga.Sdk.Api;
using OpenFga.Sdk.Client;
-using OpenFga.Sdk.Client.Model;
-using OpenFga.Sdk.Model;
-using Xunit;
namespace Fga.Net.Tests.Client;
-[Collection(nameof(EndpointWebAppCollection))]
-public class EndpointTests
+[ClassDataSource(Shared = SharedType.PerAssembly)]
+public class EndpointTests(EndpointWebAppFixture fixture) : EndpointWebAppBase(fixture)
{
- private readonly IAlbaHost _host;
-
- public EndpointTests(EndpointWebAppFixture fixture)
- {
- _host = fixture.AlbaHost;
- }
-
- [Fact]
+ [Test]
private async Task GetEndpoints_OpenFgaApi_Return_200()
{
- using var scope = _host.Services.CreateScope();
+ using var scope = Host.Services.CreateScope();
var client = scope.ServiceProvider.GetRequiredService();
var config = scope.ServiceProvider.GetRequiredService>().Value;
var modelsResponse = await client.ReadAuthorizationModels(config.StoreId!);
-
- Assert.NotNull(modelsResponse);
- Assert.NotNull(modelsResponse.AuthorizationModels);
- Assert.True(modelsResponse.AuthorizationModels?.Count > 0);
-
- var modelId = modelsResponse.AuthorizationModels?.First().Id!;
-
- var modelResponse = await client.ReadAuthorizationModel(config.StoreId!, modelId);
-
- Assert.NotNull(modelResponse);
- Assert.NotNull(modelResponse.AuthorizationModel?.Id);
-
- var assertions = await client.ReadAssertions(config.StoreId!, modelId);
-
- Assert.NotNull(assertions);
- Assert.True(assertions.Assertions?.Count > 0);
- var assertion = assertions.Assertions!.First().TupleKey;
-
- Assert.NotEmpty(assertion!.Object!);
- Assert.NotEmpty(assertion.Relation!);
- Assert.NotEmpty(assertion.User!);
-
- var graph = await client.Expand(config.StoreId!, new ExpandRequest()
- {
- AuthorizationModelId = modelId,
- TupleKey = new ExpandRequestTupleKey(assertion.Relation, assertion.Object)
- });
-
- Assert.NotNull(graph.Tree);
- Assert.NotNull(graph.Tree!.Root!.Name);
-
- var watch = await client.ReadChanges(config.StoreId!);
- Assert.NotNull(watch);
-
-
+
+ modelsResponse.Should().NotBeNull();
+ modelsResponse.AuthorizationModels.Should().NotBeNull();
+ modelsResponse.AuthorizationModels.Count.Should().BePositive();
}
- [Fact]
+ [Test]
private async Task GetEndpoints_OpenFgaClient_Return_200()
{
- using var scope = _host.Services.CreateScope();
+ using var scope = Host.Services.CreateScope();
var client = scope.ServiceProvider.GetRequiredService();
var modelsResponse = await client.ReadAuthorizationModels();
- Assert.NotNull(modelsResponse);
- Assert.NotNull(modelsResponse.AuthorizationModels);
- Assert.True(modelsResponse.AuthorizationModels?.Count > 0);
-
- var modelId = modelsResponse.AuthorizationModels?.First().Id!;
-
- var modelResponse = await client.ReadAuthorizationModel(new ClientReadAuthorizationModelOptions() {AuthorizationModelId = modelId});
-
- Assert.NotNull(modelResponse);
- Assert.NotNull(modelResponse.AuthorizationModel?.Id);
-
- var assertions = await client.ReadAssertions(new ClientReadAssertionsOptions() { AuthorizationModelId = modelId});
-
- Assert.NotNull(assertions);
- Assert.True(assertions.Assertions?.Count > 0);
- var assertion = assertions.Assertions!.First().TupleKey;
-
- Assert.NotEmpty(assertion!.Object!);
- Assert.NotEmpty(assertion.Relation!);
- Assert.NotEmpty(assertion.User!);
-
- var graph = await client.Expand(new ClientExpandRequest()
- {
- Object = assertion.Object!,
- Relation = assertion.Relation!
- });
-
- Assert.NotNull(graph.Tree);
- Assert.NotNull(graph.Tree!.Root!.Name);
-
- var watch = await client.ReadChanges(new ClientReadChangesRequest() {Type = "document"});
- Assert.NotNull(watch);
+ modelsResponse.Should().NotBeNull();
+ modelsResponse.AuthorizationModels.Should().NotBeNull();
+ modelsResponse.AuthorizationModels.Count.Should().BePositive();
}
}
\ No newline at end of file
diff --git a/tests/Fga.Net.Tests/Client/EndpointWebAppFixture.cs b/tests/Fga.Net.Tests/Client/EndpointWebAppFixture.cs
index e23a0ca..0e6d644 100644
--- a/tests/Fga.Net.Tests/Client/EndpointWebAppFixture.cs
+++ b/tests/Fga.Net.Tests/Client/EndpointWebAppFixture.cs
@@ -1,11 +1,10 @@
-using System.Threading.Tasks;
-using Alba;
+using Alba;
using Fga.Net.Tests.Middleware;
-using Xunit;
+using TUnit.Core.Interfaces;
namespace Fga.Net.Tests.Client;
-public class EndpointWebAppFixture : IAsyncLifetime
+public class EndpointWebAppFixture : IAsyncInitializer, IAsyncDisposable
{
public IAlbaHost AlbaHost = null!;
@@ -14,13 +13,13 @@ public async Task InitializeAsync()
AlbaHost = await Alba.AlbaHost.For(_ => { }, MockJwtConfiguration.GetDefaultStubConfiguration());
}
- public async Task DisposeAsync()
+ public async ValueTask DisposeAsync()
{
await AlbaHost.DisposeAsync();
}
}
-[CollectionDefinition(nameof(EndpointWebAppCollection))]
-public class EndpointWebAppCollection : ICollectionFixture
+public abstract class EndpointWebAppBase(EndpointWebAppFixture fixture)
{
+ protected IAlbaHost Host => fixture.AlbaHost;
}
\ No newline at end of file
diff --git a/tests/Fga.Net.Tests/Fga.Net.Tests.csproj b/tests/Fga.Net.Tests/Fga.Net.Tests.csproj
index 3cc8775..3bc9ec0 100644
--- a/tests/Fga.Net.Tests/Fga.Net.Tests.csproj
+++ b/tests/Fga.Net.Tests/Fga.Net.Tests.csproj
@@ -1,26 +1,19 @@
- net8.0
+ net8.0;net9.0
enable
-
+ enable
+ Exe
false
-
-
+
+
-
-
- runtime; build; native; contentfiles; analyzers; buildtransitive
- all
-
-
- runtime; build; native; contentfiles; analyzers; buildtransitive
- all
-
+
diff --git a/tests/Fga.Net.Tests/Middleware/MiddlewareTests.cs b/tests/Fga.Net.Tests/Middleware/MiddlewareTests.cs
index 510390a..e4ef112 100644
--- a/tests/Fga.Net.Tests/Middleware/MiddlewareTests.cs
+++ b/tests/Fga.Net.Tests/Middleware/MiddlewareTests.cs
@@ -1,34 +1,26 @@
-using System;
-using System.Net;
+using System.Net;
using System.Security.Claims;
-using System.Threading.Tasks;
using Alba;
-using Xunit;
namespace Fga.Net.Tests.Middleware;
-[Collection(nameof(WebAppCollection))]
-public class MiddlewareTests
+[ClassDataSource(Shared = SharedType.PerAssembly)]
+public class MiddlewareTests(WebAppFixture fixture) : WebAppBase(fixture)
{
- private readonly IAlbaHost _alba;
-
- public MiddlewareTests(WebAppFixture fixture)
- {
- _alba = fixture.AlbaHost;
- }
- [Fact]
+ [Test]
public async Task Authorization_HappyPath_Succeeds()
{
- await _alba.Scenario(_ =>
+ await Host.Scenario(_ =>
{
_.Get.Url($"/test/{Guid.NewGuid()}");
_.StatusCodeShouldBeOk();
});
}
- [Fact]
+
+ [Test]
public async Task Authorization_UnhappyPath_Forbidden()
{
- await _alba.Scenario(_ =>
+ await Host.Scenario(_ =>
{
_.RemoveClaim(ClaimTypes.NameIdentifier);
_.WithClaim(new Claim(ClaimTypes.NameIdentifier, MockJwtConfiguration.FakeUser));
diff --git a/tests/Fga.Net.Tests/Middleware/WebAppFixture.cs b/tests/Fga.Net.Tests/Middleware/WebAppFixture.cs
index eaaa0a0..a0f3c92 100644
--- a/tests/Fga.Net.Tests/Middleware/WebAppFixture.cs
+++ b/tests/Fga.Net.Tests/Middleware/WebAppFixture.cs
@@ -1,19 +1,14 @@
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-using Alba;
+using Alba;
using Fga.Net.AspNetCore.Authorization;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Moq;
using OpenFga.Sdk.Client.Model;
-using OpenFga.Sdk.Model;
-using Xunit;
+using TUnit.Core.Interfaces;
namespace Fga.Net.Tests.Middleware;
-public class WebAppFixture : IAsyncLifetime
+public class WebAppFixture : IAsyncInitializer, IAsyncDisposable
{
public IAlbaHost AlbaHost = null!;
@@ -28,12 +23,10 @@ public async Task InitializeAsync()
{
var entry = res.First();
return entry.User == $"user:{MockJwtConfiguration.DefaultUser}"
- ? new BatchCheckResponse() { Responses = new List() { new(true, entry) } }
- : new BatchCheckResponse() { Responses = new List() { new(false, entry) } };
+ ? new BatchCheckResponse() { Responses = [new(true, entry)] }
+ : new BatchCheckResponse() { Responses = [new(false, entry)] };
});
-
-
AlbaHost = await Alba.AlbaHost.For(builder =>
{
builder.ConfigureServices(s =>
@@ -44,14 +37,14 @@ public async Task InitializeAsync()
}, MockJwtConfiguration.GetDefaultStubConfiguration());
}
- public async Task DisposeAsync()
+ public async ValueTask DisposeAsync()
{
if (AlbaHost is not null)
await AlbaHost.DisposeAsync();
}
}
-[CollectionDefinition(nameof(WebAppCollection))]
-public class WebAppCollection : ICollectionFixture
+public abstract class WebAppBase(WebAppFixture fixture)
{
+ protected IAlbaHost Host => fixture.AlbaHost;
}
\ No newline at end of file
diff --git a/tests/Fga.Net.Tests/TheoryData.cs b/tests/Fga.Net.Tests/TheoryData.cs
deleted file mode 100644
index 67d48d3..0000000
--- a/tests/Fga.Net.Tests/TheoryData.cs
+++ /dev/null
@@ -1,25 +0,0 @@
-using System.Collections;
-using System.Collections.Generic;
-
-namespace Fga.Net.Tests;
-
-// https://andrewlock.net/creating-strongly-typed-xunit-theory-test-data-with-theorydata/
-public abstract class TheoryData : IEnumerable