diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 00000000..2f7e5847
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,28 @@
+# EditorConfig
+
+# top-most EditorConfig file
+root = true
+
+# Unix-style newlines with a newline ending every file
+[*]
+charset = utf-8
+end_of_line = lf
+insert_final_newline = true
+trim_trailing_whitespace = true
+
+[*.json]
+indent_size = 4
+indent_style = space
+
+[*.{markdown,md}]
+indent_size = 4
+indent_style = space
+trim_trailing_whitespace = false
+
+[*.xml]
+indent_size = 4
+indent_style = space
+
+[*.{yaml,yml}]
+indent_size = 2
+indent_style = space
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
new file mode 100644
index 00000000..d4efe157
--- /dev/null
+++ b/.github/workflows/test.yml
@@ -0,0 +1,27 @@
+name: Build & Run Tests
+env:
+ DOTNET_CLI_TELEMETRY_OPTOUT: 1
+
+on:
+ push:
+ branches:
+ - master
+ pull_request:
+
+jobs:
+ Test:
+ runs-on: windows-latest
+ steps:
+ - uses: actions/checkout@v2
+ - name: Setup .NET Core
+ uses: actions/setup-dotnet@v1.7.2
+ with:
+ dotnet-version: 5.x
+ - name: Build with dotnet
+ run: dotnet build -c Release
+ - name: Run tests with coverage
+ run: dotnet test ./UKSF.Api.sln -c Release --no-build /p:CollectCoverage=true /p:CoverletOutputFormat=lcov /p:CoverletOutput=../coverage/lcov.info /p:Exclude="[UKSF.PostMessage]*"
+ - name: Coveralls
+ uses: coverallsapp/github-action@master
+ with:
+ github-token: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.gitignore b/.gitignore
index 5b63458e..461fa936 100644
--- a/.gitignore
+++ b/.gitignore
@@ -232,7 +232,6 @@ _Pvt_Extensions
# Sensitive configs
**/appconfig/**
-/UKSFWebsite.Api/website-backend-config/**
**/build_output/**
**/build_tests/**
**/__pycache__/**
@@ -260,5 +259,5 @@ coverage.xml
.idea/
# Specific
-!UKSFWebsite.Api.Services/Debug**
appsettings.Development.json
+*.info
diff --git a/.vscode/launch.json b/.vscode/launch.json
deleted file mode 100644
index 5dffe88a..00000000
--- a/.vscode/launch.json
+++ /dev/null
@@ -1,28 +0,0 @@
-{
- // Use IntelliSense to find out which attributes exist for C# debugging
- // Use hover for the description of the existing attributes
- // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md
- "version": "0.2.0",
- "configurations": [
- {
- "name": ".NET Core Launch (console)",
- "type": "coreclr",
- "request": "launch",
- "preLaunchTask": "build",
- // If you have changed target frameworks, make sure to update the program path.
- "program": "${workspaceFolder}/TaskRunner/bin/Debug/netcoreapp2.1/TaskRunner.dll",
- "args": [],
- "cwd": "${workspaceFolder}/TaskRunner",
- // For more information about the 'console' field, see https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md#console-terminal-window
- "console": "internalConsole",
- "stopAtEntry": false,
- "internalConsoleOptions": "openOnSessionStart"
- },
- {
- "name": ".NET Core Attach",
- "type": "coreclr",
- "request": "attach",
- "processId": "${command:pickProcess}"
- }
- ,]
-}
\ No newline at end of file
diff --git a/.vscode/tasks.json b/.vscode/tasks.json
deleted file mode 100644
index 6e27c3df..00000000
--- a/.vscode/tasks.json
+++ /dev/null
@@ -1,15 +0,0 @@
-{
- "version": "2.0.0",
- "tasks": [
- {
- "label": "build",
- "command": "dotnet",
- "type": "process",
- "args": [
- "build",
- "${workspaceFolder}/UKSFWebsite.Api/UKSFWebsite.Api.csproj"
- ],
- "problemMatcher": "$msCompile"
- }
- ]
-}
diff --git a/NuGet.Config b/NuGet.Config
index acd3bb9e..3ae0b41c 100644
--- a/NuGet.Config
+++ b/NuGet.Config
@@ -5,8 +5,7 @@
-
-
+
diff --git a/README.md b/README.md
index 729a71f3..7982cc61 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,3 @@
# UKSF Website Backend
+
+[](https://coveralls.io/github/uksf/api?branch=master)
diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj
new file mode 100644
index 00000000..cbfa5815
--- /dev/null
+++ b/Tests/Tests.csproj
@@ -0,0 +1,7 @@
+
+
+
+ net5.0
+
+
+
diff --git a/Tests/UKSF.Api.Admin.Tests/DependencyInjectionTests.cs b/Tests/UKSF.Api.Admin.Tests/DependencyInjectionTests.cs
new file mode 100644
index 00000000..c86bf7cf
--- /dev/null
+++ b/Tests/UKSF.Api.Admin.Tests/DependencyInjectionTests.cs
@@ -0,0 +1,49 @@
+using FluentAssertions;
+using Microsoft.Extensions.DependencyInjection;
+using UKSF.Api.Admin.Controllers;
+using UKSF.Api.Admin.EventHandlers;
+using UKSF.Api.Admin.ScheduledActions;
+using UKSF.Api.Tests.Common;
+using Xunit;
+
+namespace UKSF.Api.Admin.Tests
+{
+ public class DependencyInjectionTests : DependencyInjectionTestsBase
+ {
+ public DependencyInjectionTests()
+ {
+ Services.AddUksfAdmin();
+ }
+
+ [Fact]
+ public void When_resolving_controllers()
+ {
+ Services.AddTransient();
+ Services.AddTransient();
+ Services.AddTransient();
+ ServiceProvider serviceProvider = Services.BuildServiceProvider();
+
+ serviceProvider.GetRequiredService().Should().NotBeNull();
+ serviceProvider.GetRequiredService().Should().NotBeNull();
+ serviceProvider.GetRequiredService().Should().NotBeNull();
+ }
+
+ [Fact]
+ public void When_resolving_event_handlers()
+ {
+ Services.AddTransient();
+ ServiceProvider serviceProvider = Services.BuildServiceProvider();
+
+ serviceProvider.GetRequiredService().Should().NotBeNull();
+ }
+
+ [Fact]
+ public void When_resolving_scheduled_actions()
+ {
+ Services.AddTransient();
+ ServiceProvider serviceProvider = Services.BuildServiceProvider();
+
+ serviceProvider.GetRequiredService().Should().NotBeNull();
+ }
+ }
+}
diff --git a/Tests/UKSF.Api.Admin.Tests/UKSF.Api.Admin.Tests.csproj b/Tests/UKSF.Api.Admin.Tests/UKSF.Api.Admin.Tests.csproj
new file mode 100644
index 00000000..dbefeb74
--- /dev/null
+++ b/Tests/UKSF.Api.Admin.Tests/UKSF.Api.Admin.Tests.csproj
@@ -0,0 +1,28 @@
+
+
+
+ net5.0
+
+ false
+
+
+
+
+
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+
+
+
+
+
+
+
diff --git a/Tests/UKSF.Api.ArmaMissions.Tests/UKSF.Api.ArmaMissions.Tests.csproj b/Tests/UKSF.Api.ArmaMissions.Tests/UKSF.Api.ArmaMissions.Tests.csproj
new file mode 100644
index 00000000..f17150b9
--- /dev/null
+++ b/Tests/UKSF.Api.ArmaMissions.Tests/UKSF.Api.ArmaMissions.Tests.csproj
@@ -0,0 +1,22 @@
+
+
+
+ net5.0
+
+ false
+
+
+
+
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+
+
diff --git a/Tests/UKSF.Api.ArmaServer.Tests/DependencyInjectionTests.cs b/Tests/UKSF.Api.ArmaServer.Tests/DependencyInjectionTests.cs
new file mode 100644
index 00000000..4d71c1a5
--- /dev/null
+++ b/Tests/UKSF.Api.ArmaServer.Tests/DependencyInjectionTests.cs
@@ -0,0 +1,31 @@
+using FluentAssertions;
+using Microsoft.Extensions.DependencyInjection;
+using UKSF.Api.Admin;
+using UKSF.Api.ArmaMissions;
+using UKSF.Api.ArmaServer.Controllers;
+using UKSF.Api.Personnel;
+using UKSF.Api.Tests.Common;
+using Xunit;
+
+namespace UKSF.Api.ArmaServer.Tests
+{
+ public class DependencyInjectionTests : DependencyInjectionTestsBase
+ {
+ public DependencyInjectionTests()
+ {
+ Services.AddUksfAdmin();
+ Services.AddUksfPersonnel();
+ Services.AddUksfArmaMissions();
+ Services.AddUksfArmaServer();
+ }
+
+ [Fact]
+ public void When_resolving_controllers()
+ {
+ Services.AddTransient();
+ ServiceProvider serviceProvider = Services.BuildServiceProvider();
+
+ serviceProvider.GetRequiredService().Should().NotBeNull();
+ }
+ }
+}
diff --git a/Tests/UKSF.Api.ArmaServer.Tests/UKSF.Api.ArmaServer.Tests.csproj b/Tests/UKSF.Api.ArmaServer.Tests/UKSF.Api.ArmaServer.Tests.csproj
new file mode 100644
index 00000000..78c0a0d1
--- /dev/null
+++ b/Tests/UKSF.Api.ArmaServer.Tests/UKSF.Api.ArmaServer.Tests.csproj
@@ -0,0 +1,28 @@
+
+
+
+ net5.0
+
+ false
+
+
+
+
+
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+
+
+
+
+
+
+
diff --git a/Tests/UKSF.Api.Auth.Tests/Controllers/AuthControllerTests.cs b/Tests/UKSF.Api.Auth.Tests/Controllers/AuthControllerTests.cs
new file mode 100644
index 00000000..97ee3183
--- /dev/null
+++ b/Tests/UKSF.Api.Auth.Tests/Controllers/AuthControllerTests.cs
@@ -0,0 +1,105 @@
+using System;
+using System.Threading.Tasks;
+using FluentAssertions;
+using MongoDB.Bson;
+using Moq;
+using UKSF.Api.Auth.Commands;
+using UKSF.Api.Auth.Controllers;
+using UKSF.Api.Auth.Exceptions;
+using UKSF.Api.Auth.Services;
+using UKSF.Api.Shared.Exceptions;
+using UKSF.Api.Shared.Services;
+using UKSF.Api.Tests.Common;
+using Xunit;
+
+namespace UKSF.Api.Auth.Tests.Controllers
+{
+ public class AuthControllerTests
+ {
+ private readonly Mock _mockHttpContextService;
+ private readonly Mock _mockLoginService;
+ private readonly Mock _mockRequestPasswordResetCommand;
+ private readonly Mock _mockResetPasswordCommand;
+ private readonly AuthController _subject;
+ private readonly string _userId = ObjectId.GenerateNewId().ToString();
+
+ public AuthControllerTests()
+ {
+ _mockLoginService = new();
+ _mockHttpContextService = new();
+ _mockRequestPasswordResetCommand = new();
+ _mockResetPasswordCommand = new();
+
+ _subject = new(_mockLoginService.Object, _mockHttpContextService.Object, _mockRequestPasswordResetCommand.Object, _mockResetPasswordCommand.Object);
+ }
+
+ [Fact]
+ public void When_getting_is_user_authed()
+ {
+ _mockHttpContextService.Setup(x => x.IsUserAuthenticated()).Returns(true);
+
+ bool result = _subject.IsUserAuthenticated();
+
+ result.Should().BeTrue();
+ }
+
+ [Fact]
+ public void When_logging_in()
+ {
+ _mockLoginService.Setup(x => x.Login("email", "password")).Returns("token");
+
+ string result = _subject.Login(new() { Email = "email", Password = "password" });
+
+ result.Should().Be("token");
+ }
+
+ [Fact]
+ public void When_refreshing_token()
+ {
+ _mockHttpContextService.Setup(x => x.GetUserId()).Returns(_userId);
+ _mockLoginService.Setup(x => x.RegenerateBearerToken(_userId)).Returns("token");
+
+ string result = _subject.RefreshToken();
+
+ result.Should().Be("token");
+ }
+
+ [Fact]
+ public void When_refreshing_token_fails()
+ {
+ _mockHttpContextService.Setup(x => x.GetUserId()).Returns(_userId);
+ _mockLoginService.Setup(x => x.RegenerateBearerToken(_userId)).Returns((string) null);
+
+ Action act = () => _subject.RefreshToken();
+
+ act.Should().Throw().WithMessageAndStatusCode("Failed to refresh token", 401);
+ }
+
+ [Fact]
+ public void When_requesting_password_reset()
+ {
+ _subject.RequestPasswordReset(new() { Email = "email" });
+
+ _mockRequestPasswordResetCommand.Verify(x => x.ExecuteAsync(It.Is(m => m.Email == "email")), Times.Once);
+ }
+
+ [Fact]
+ public async Task When_resetting_password()
+ {
+ _mockResetPasswordCommand.Setup(x => x.ExecuteAsync(It.Is(m => m.Email == "email" && m.Password == "password" && m.Code == "code")));
+ _mockLoginService.Setup(x => x.LoginForPasswordReset("email")).Returns("token");
+
+ string result = await _subject.ResetPassword("code", new() { Email = "email", Password = "password" });
+
+ result.Should().Be("token");
+ }
+
+ [Theory, InlineData(null, "password"), InlineData("email", null)]
+ public void When_logging_in_with_invalid_credentials(string email, string password)
+ {
+ Action act = () => _subject.Login(new() { Email = email, Password = password });
+
+ act.Should().Throw().WithMessageAndStatusCode("Bad request", 400);
+ }
+ }
+}
diff --git a/Tests/UKSF.Api.Auth.Tests/DependencyInjectionTests.cs b/Tests/UKSF.Api.Auth.Tests/DependencyInjectionTests.cs
new file mode 100644
index 00000000..f15304fb
--- /dev/null
+++ b/Tests/UKSF.Api.Auth.Tests/DependencyInjectionTests.cs
@@ -0,0 +1,29 @@
+using FluentAssertions;
+using Microsoft.Extensions.DependencyInjection;
+using UKSF.Api.Admin;
+using UKSF.Api.Auth.Controllers;
+using UKSF.Api.Personnel;
+using UKSF.Api.Tests.Common;
+using Xunit;
+
+namespace UKSF.Api.Auth.Tests
+{
+ public class DependencyInjectionTests : DependencyInjectionTestsBase
+ {
+ public DependencyInjectionTests()
+ {
+ Services.AddUksfAdmin();
+ Services.AddUksfPersonnel();
+ Services.AddUksfAuth(Configuration);
+ }
+
+ [Fact]
+ public void When_resolving_controllers()
+ {
+ Services.AddTransient();
+ ServiceProvider serviceProvider = Services.BuildServiceProvider();
+
+ serviceProvider.GetRequiredService().Should().NotBeNull();
+ }
+ }
+}
diff --git a/Tests/UKSF.Api.Auth.Tests/UKSF.Api.Auth.Tests.csproj b/Tests/UKSF.Api.Auth.Tests/UKSF.Api.Auth.Tests.csproj
new file mode 100644
index 00000000..279d9efe
--- /dev/null
+++ b/Tests/UKSF.Api.Auth.Tests/UKSF.Api.Auth.Tests.csproj
@@ -0,0 +1,28 @@
+
+
+
+ net5.0
+
+ false
+
+
+
+
+
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+
+
+
+
+
+
+
diff --git a/Tests/UKSF.Api.Base.Tests/UKSF.Api.Base.Tests.csproj b/Tests/UKSF.Api.Base.Tests/UKSF.Api.Base.Tests.csproj
new file mode 100644
index 00000000..04d2fe59
--- /dev/null
+++ b/Tests/UKSF.Api.Base.Tests/UKSF.Api.Base.Tests.csproj
@@ -0,0 +1,30 @@
+
+
+
+ net5.0
+
+ false
+
+
+
+
+
+
+
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+
+
+
+
+
+
+
diff --git a/Tests/UKSF.Api.Command.Tests/DependencyInjectionTests.cs b/Tests/UKSF.Api.Command.Tests/DependencyInjectionTests.cs
new file mode 100644
index 00000000..d8bd1ae1
--- /dev/null
+++ b/Tests/UKSF.Api.Command.Tests/DependencyInjectionTests.cs
@@ -0,0 +1,47 @@
+using FluentAssertions;
+using Microsoft.Extensions.DependencyInjection;
+using UKSF.Api.Admin;
+using UKSF.Api.Command.Controllers;
+using UKSF.Api.Command.EventHandlers;
+using UKSF.Api.Personnel;
+using UKSF.Api.Tests.Common;
+using Xunit;
+
+namespace UKSF.Api.Command.Tests
+{
+ public class DependencyInjectionTests : DependencyInjectionTestsBase
+ {
+ public DependencyInjectionTests()
+ {
+ Services.AddUksfAdmin();
+ Services.AddUksfPersonnel();
+ Services.AddUksfCommand();
+ }
+
+ [Fact]
+ public void When_resolving_controllers()
+ {
+ Services.AddTransient();
+ Services.AddTransient();
+ Services.AddTransient();
+ Services.AddTransient();
+ Services.AddTransient();
+ ServiceProvider serviceProvider = Services.BuildServiceProvider();
+
+ serviceProvider.GetRequiredService().Should().NotBeNull();
+ serviceProvider.GetRequiredService().Should().NotBeNull();
+ serviceProvider.GetRequiredService().Should().NotBeNull();
+ serviceProvider.GetRequiredService().Should().NotBeNull();
+ serviceProvider.GetRequiredService().Should().NotBeNull();
+ }
+
+ [Fact]
+ public void When_resolving_event_handlers()
+ {
+ Services.AddTransient();
+ ServiceProvider serviceProvider = Services.BuildServiceProvider();
+
+ serviceProvider.GetRequiredService().Should().NotBeNull();
+ }
+ }
+}
diff --git a/Tests/UKSF.Api.Command.Tests/UKSF.Api.Command.Tests.csproj b/Tests/UKSF.Api.Command.Tests/UKSF.Api.Command.Tests.csproj
new file mode 100644
index 00000000..bd7c223e
--- /dev/null
+++ b/Tests/UKSF.Api.Command.Tests/UKSF.Api.Command.Tests.csproj
@@ -0,0 +1,28 @@
+
+
+
+ net5.0
+
+ false
+
+
+
+
+
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+
+
+
+
+
+
+
diff --git a/Tests/UKSF.Api.Integrations.Discord.Tests/DependencyInjectionTests.cs b/Tests/UKSF.Api.Integrations.Discord.Tests/DependencyInjectionTests.cs
new file mode 100644
index 00000000..97a4d5e3
--- /dev/null
+++ b/Tests/UKSF.Api.Integrations.Discord.Tests/DependencyInjectionTests.cs
@@ -0,0 +1,40 @@
+using FluentAssertions;
+using Microsoft.Extensions.DependencyInjection;
+using UKSF.Api.Admin;
+using UKSF.Api.Discord;
+using UKSF.Api.Discord.Controllers;
+using UKSF.Api.Discord.EventHandlers;
+using UKSF.Api.Personnel;
+using UKSF.Api.Tests.Common;
+using Xunit;
+
+namespace UKSF.Api.Integrations.Discord.Tests
+{
+ public class DependencyInjectionTests : DependencyInjectionTestsBase
+ {
+ public DependencyInjectionTests()
+ {
+ Services.AddUksfAdmin();
+ Services.AddUksfPersonnel();
+ Services.AddUksfIntegrationDiscord();
+ }
+
+ [Fact]
+ public void When_resolving_controllers()
+ {
+ Services.AddTransient();
+ ServiceProvider serviceProvider = Services.BuildServiceProvider();
+
+ serviceProvider.GetRequiredService().Should().NotBeNull();
+ }
+
+ [Fact]
+ public void When_resolving_event_handlers()
+ {
+ Services.AddTransient();
+ ServiceProvider serviceProvider = Services.BuildServiceProvider();
+
+ serviceProvider.GetRequiredService().Should().NotBeNull();
+ }
+ }
+}
diff --git a/Tests/UKSF.Api.Integrations.Discord.Tests/UKSF.Api.Integrations.Discord.Tests.csproj b/Tests/UKSF.Api.Integrations.Discord.Tests/UKSF.Api.Integrations.Discord.Tests.csproj
new file mode 100644
index 00000000..a74d9494
--- /dev/null
+++ b/Tests/UKSF.Api.Integrations.Discord.Tests/UKSF.Api.Integrations.Discord.Tests.csproj
@@ -0,0 +1,28 @@
+
+
+
+ net5.0
+
+ false
+
+
+
+
+
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+
+
+
+
+
+
+
diff --git a/Tests/UKSF.Api.Integrations.Instagram.Tests/DependencyInjectionTests.cs b/Tests/UKSF.Api.Integrations.Instagram.Tests/DependencyInjectionTests.cs
new file mode 100644
index 00000000..b457e628
--- /dev/null
+++ b/Tests/UKSF.Api.Integrations.Instagram.Tests/DependencyInjectionTests.cs
@@ -0,0 +1,39 @@
+using FluentAssertions;
+using Microsoft.Extensions.DependencyInjection;
+using UKSF.Api.Admin;
+using UKSF.Api.Integrations.Instagram.Controllers;
+using UKSF.Api.Integrations.Instagram.ScheduledActions;
+using UKSF.Api.Tests.Common;
+using Xunit;
+
+namespace UKSF.Api.Integrations.Instagram.Tests
+{
+ public class DependencyInjectionTests : DependencyInjectionTestsBase
+ {
+ public DependencyInjectionTests()
+ {
+ Services.AddUksfAdmin();
+ Services.AddUksfIntegrationInstagram();
+ }
+
+ [Fact]
+ public void When_resolving_controllers()
+ {
+ Services.AddTransient();
+ ServiceProvider serviceProvider = Services.BuildServiceProvider();
+
+ serviceProvider.GetRequiredService().Should().NotBeNull();
+ }
+
+ [Fact]
+ public void When_resolving_scheduled_actions()
+ {
+ Services.AddTransient();
+ Services.AddTransient();
+ ServiceProvider serviceProvider = Services.BuildServiceProvider();
+
+ serviceProvider.GetRequiredService().Should().NotBeNull();
+ serviceProvider.GetRequiredService().Should().NotBeNull();
+ }
+ }
+}
diff --git a/Tests/UKSF.Api.Integrations.Instagram.Tests/UKSF.Api.Integrations.Instagram.Tests.csproj b/Tests/UKSF.Api.Integrations.Instagram.Tests/UKSF.Api.Integrations.Instagram.Tests.csproj
new file mode 100644
index 00000000..0ae0f3a0
--- /dev/null
+++ b/Tests/UKSF.Api.Integrations.Instagram.Tests/UKSF.Api.Integrations.Instagram.Tests.csproj
@@ -0,0 +1,28 @@
+
+
+
+ net5.0
+
+ false
+
+
+
+
+
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+
+
+
+
+
+
+
diff --git a/Tests/UKSF.Api.Integrations.Teamspeak.Tests/DependencyInjectionTests.cs b/Tests/UKSF.Api.Integrations.Teamspeak.Tests/DependencyInjectionTests.cs
new file mode 100644
index 00000000..7aefdcd2
--- /dev/null
+++ b/Tests/UKSF.Api.Integrations.Teamspeak.Tests/DependencyInjectionTests.cs
@@ -0,0 +1,54 @@
+using FluentAssertions;
+using Microsoft.Extensions.DependencyInjection;
+using UKSF.Api.Admin;
+using UKSF.Api.Personnel;
+using UKSF.Api.Teamspeak;
+using UKSF.Api.Teamspeak.Controllers;
+using UKSF.Api.Teamspeak.EventHandlers;
+using UKSF.Api.Teamspeak.ScheduledActions;
+using UKSF.Api.Tests.Common;
+using Xunit;
+
+namespace UKSF.Api.Integrations.Teamspeak.Tests
+{
+ public class DependencyInjectionTests : DependencyInjectionTestsBase
+ {
+ public DependencyInjectionTests()
+ {
+ Services.AddUksfAdmin();
+ Services.AddUksfPersonnel();
+ Services.AddUksfIntegrationTeamspeak();
+ }
+
+ [Fact]
+ public void When_resolving_controllers()
+ {
+ Services.AddTransient();
+ Services.AddTransient();
+ ServiceProvider serviceProvider = Services.BuildServiceProvider();
+
+ serviceProvider.GetRequiredService().Should().NotBeNull();
+ serviceProvider.GetRequiredService().Should().NotBeNull();
+ }
+
+ [Fact]
+ public void When_resolving_event_handlers()
+ {
+ Services.AddTransient();
+ Services.AddTransient();
+ ServiceProvider serviceProvider = Services.BuildServiceProvider();
+
+ serviceProvider.GetRequiredService().Should().NotBeNull();
+ serviceProvider.GetRequiredService().Should().NotBeNull();
+ }
+
+ [Fact]
+ public void When_resolving_scheduled_actions()
+ {
+ Services.AddTransient();
+ ServiceProvider serviceProvider = Services.BuildServiceProvider();
+
+ serviceProvider.GetRequiredService().Should().NotBeNull();
+ }
+ }
+}
diff --git a/Tests/UKSF.Api.Integrations.Teamspeak.Tests/UKSF.Api.Integrations.Teamspeak.Tests.csproj b/Tests/UKSF.Api.Integrations.Teamspeak.Tests/UKSF.Api.Integrations.Teamspeak.Tests.csproj
new file mode 100644
index 00000000..fbb0f7ed
--- /dev/null
+++ b/Tests/UKSF.Api.Integrations.Teamspeak.Tests/UKSF.Api.Integrations.Teamspeak.Tests.csproj
@@ -0,0 +1,28 @@
+
+
+
+ net5.0
+
+ false
+
+
+
+
+
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+
+
+
+
+
+
+
diff --git a/Tests/UKSF.Api.Launcher.Tests/DependencyInjectionTests.cs b/Tests/UKSF.Api.Launcher.Tests/DependencyInjectionTests.cs
new file mode 100644
index 00000000..a53fcdfb
--- /dev/null
+++ b/Tests/UKSF.Api.Launcher.Tests/DependencyInjectionTests.cs
@@ -0,0 +1,29 @@
+using FluentAssertions;
+using Microsoft.Extensions.DependencyInjection;
+using UKSF.Api.Admin;
+using UKSF.Api.Launcher.Controllers;
+using UKSF.Api.Personnel;
+using UKSF.Api.Tests.Common;
+using Xunit;
+
+namespace UKSF.Api.Launcher.Tests
+{
+ public class DependencyInjectionTests : DependencyInjectionTestsBase
+ {
+ public DependencyInjectionTests()
+ {
+ Services.AddUksfAdmin();
+ Services.AddUksfPersonnel();
+ Services.AddUksfLauncher();
+ }
+
+ [Fact]
+ public void When_resolving_controllers()
+ {
+ Services.AddTransient();
+ ServiceProvider serviceProvider = Services.BuildServiceProvider();
+
+ serviceProvider.GetRequiredService().Should().NotBeNull();
+ }
+ }
+}
diff --git a/Tests/UKSF.Api.Launcher.Tests/UKSF.Api.Launcher.Tests.csproj b/Tests/UKSF.Api.Launcher.Tests/UKSF.Api.Launcher.Tests.csproj
new file mode 100644
index 00000000..488458cf
--- /dev/null
+++ b/Tests/UKSF.Api.Launcher.Tests/UKSF.Api.Launcher.Tests.csproj
@@ -0,0 +1,28 @@
+
+
+
+ net5.0
+
+ false
+
+
+
+
+
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+
+
+
+
+
+
+
diff --git a/Tests/UKSF.Api.Modpack.Tests/BuildsServiceTests.cs b/Tests/UKSF.Api.Modpack.Tests/BuildsServiceTests.cs
new file mode 100644
index 00000000..a412dee2
--- /dev/null
+++ b/Tests/UKSF.Api.Modpack.Tests/BuildsServiceTests.cs
@@ -0,0 +1,45 @@
+using Moq;
+using UKSF.Api.Modpack.Context;
+using UKSF.Api.Modpack.Services;
+using UKSF.Api.Modpack.Services.BuildProcess;
+using UKSF.Api.Personnel.Context;
+using UKSF.Api.Shared.Events;
+using UKSF.Api.Shared.Services;
+
+namespace UKSF.Api.Modpack.Tests
+{
+ public class BuildsServiceTests
+ {
+ private readonly Mock _mockAccountContext;
+ private readonly Mock _mockBuildsContext;
+ private readonly Mock _mockBuildStepService;
+ private readonly BuildsService _subject;
+
+ public BuildsServiceTests()
+ {
+ _mockBuildsContext = new();
+ _mockBuildStepService = new();
+ _mockAccountContext = new();
+ Mock mockHttpContextService = new();
+ Mock mockLogger = new();
+
+ _subject = new(_mockBuildsContext.Object, _mockBuildStepService.Object, _mockAccountContext.Object, mockHttpContextService.Object, mockLogger.Object);
+ }
+
+ // [Fact]
+ // public async Task When_creating_rc_build()
+ // {
+ // _mockBuildsContext.Setup(x => x.Get(It.IsAny>())).Returns(new List());
+ // _mockAccountContext.Setup(x => x.GetSingle(It.IsAny>())).Returns(new DomainAccount { Id = "accountId" });
+ // _mockBuildStepService.Setup(x => x.GetSteps(GameEnvironment.RC)).Returns(new List());
+ //
+ // GithubCommit githubCommit = new() { Author = "author" };
+ // ModpackBuild result = await _subject.CreateRcBuild("1.1.0", githubCommit);
+ //
+ // result.Environment.Should().Be(GameEnvironment.RC);
+ // result.BuildNumber.Should().Be(1);
+ // result.BuilderId.Should().Be("accountId");
+ // result.EnvironmentVariables.Should().BeEquivalentTo(new Dictionary { { "ace_updated", true }, { "acre_updated", true }, { "uksf_air_updated", true } });
+ // }
+ }
+}
diff --git a/Tests/UKSF.Api.Modpack.Tests/DependencyInjectionTests.cs b/Tests/UKSF.Api.Modpack.Tests/DependencyInjectionTests.cs
new file mode 100644
index 00000000..7e9ccb61
--- /dev/null
+++ b/Tests/UKSF.Api.Modpack.Tests/DependencyInjectionTests.cs
@@ -0,0 +1,59 @@
+using FluentAssertions;
+using Microsoft.Extensions.DependencyInjection;
+using UKSF.Api.Admin;
+using UKSF.Api.ArmaMissions;
+using UKSF.Api.ArmaServer;
+using UKSF.Api.Discord;
+using UKSF.Api.Modpack.Controllers;
+using UKSF.Api.Modpack.EventHandlers;
+using UKSF.Api.Modpack.ScheduledActions;
+using UKSF.Api.Personnel;
+using UKSF.Api.Tests.Common;
+using Xunit;
+
+namespace UKSF.Api.Modpack.Tests
+{
+ public class DependencyInjectionTests : DependencyInjectionTestsBase
+ {
+ public DependencyInjectionTests()
+ {
+ Services.AddUksfAdmin();
+ Services.AddUksfPersonnel();
+ Services.AddUksfArmaMissions();
+ Services.AddUksfArmaServer();
+ Services.AddUksfIntegrationDiscord();
+ Services.AddUksfModpack();
+ }
+
+ [Fact]
+ public void When_resolving_controllers()
+ {
+ Services.AddTransient();
+ Services.AddTransient();
+ Services.AddTransient();
+ ServiceProvider serviceProvider = Services.BuildServiceProvider();
+
+ serviceProvider.GetRequiredService().Should().NotBeNull();
+ serviceProvider.GetRequiredService().Should().NotBeNull();
+ serviceProvider.GetRequiredService().Should().NotBeNull();
+ }
+
+ [Fact]
+ public void When_resolving_event_handlers()
+ {
+ Services.AddTransient();
+ ServiceProvider serviceProvider = Services.BuildServiceProvider();
+
+ serviceProvider.GetRequiredService().Should().NotBeNull();
+ }
+
+ [Fact]
+ public void When_resolving_scheduled_actions()
+ {
+ Services.AddTransient();
+ ServiceProvider serviceProvider = Services.BuildServiceProvider();
+
+ serviceProvider.GetRequiredService().Should().NotBeNull();
+ }
+ }
+}
diff --git a/Tests/UKSF.Api.Modpack.Tests/UKSF.Api.Modpack.Tests.csproj b/Tests/UKSF.Api.Modpack.Tests/UKSF.Api.Modpack.Tests.csproj
new file mode 100644
index 00000000..8dd260f3
--- /dev/null
+++ b/Tests/UKSF.Api.Modpack.Tests/UKSF.Api.Modpack.Tests.csproj
@@ -0,0 +1,28 @@
+
+
+
+ net5.0
+
+ false
+
+
+
+
+
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+
+
+
+
+
+
+
diff --git a/Tests/UKSF.Api.Personnel.Tests/Commands/ConnectTeamspeakIdToAccountCommandTests.cs b/Tests/UKSF.Api.Personnel.Tests/Commands/ConnectTeamspeakIdToAccountCommandTests.cs
new file mode 100644
index 00000000..dadddf24
--- /dev/null
+++ b/Tests/UKSF.Api.Personnel.Tests/Commands/ConnectTeamspeakIdToAccountCommandTests.cs
@@ -0,0 +1,97 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using FluentAssertions;
+using MongoDB.Bson;
+using MongoDB.Driver;
+using Moq;
+using UKSF.Api.Base.Events;
+using UKSF.Api.Personnel.Commands;
+using UKSF.Api.Personnel.Context;
+using UKSF.Api.Personnel.Exceptions;
+using UKSF.Api.Personnel.Models;
+using UKSF.Api.Personnel.Services;
+using UKSF.Api.Shared.Events;
+using UKSF.Api.Tests.Common;
+using Xunit;
+
+namespace UKSF.Api.Personnel.Tests.Commands
+{
+ public class ConnectTeamspeakIdToAccountCommandTests
+ {
+ private readonly string _accountId = ObjectId.GenerateNewId().ToString();
+ private readonly string _confirmationCode = ObjectId.GenerateNewId().ToString();
+ private readonly Mock _mockAccountContext;
+ private readonly Mock _mockConfirmationCodeService;
+ private readonly Mock _mockEventBus;
+ private readonly Mock _mockLogger;
+ private readonly Mock _mockNotificationsService;
+ private readonly ConnectTeamspeakIdToAccountCommand _subject;
+ private readonly string _teamspeakId = "2";
+
+ public ConnectTeamspeakIdToAccountCommandTests()
+ {
+ _mockEventBus = new();
+ _mockLogger = new();
+ _mockAccountContext = new();
+ _mockConfirmationCodeService = new();
+ _mockNotificationsService = new();
+
+ _subject = new(_mockEventBus.Object, _mockLogger.Object, _mockAccountContext.Object, _mockConfirmationCodeService.Object, _mockNotificationsService.Object);
+ }
+
+ [Fact]
+ public async Task When_connecting_teamspeak_id()
+ {
+ _mockConfirmationCodeService.Setup(x => x.GetConfirmationCodeValue(_confirmationCode)).ReturnsAsync(_teamspeakId);
+
+ BsonValue expectedUpdate = Builders.Update.Set(x => x.TeamspeakIdentities, new() { 2 }).RenderUpdate();
+ BsonValue createdUpdate = null;
+ _mockAccountContext.Setup(x => x.Update(_accountId, It.IsAny>()))
+ .Callback((string _, UpdateDefinition update) => createdUpdate = update.RenderUpdate());
+ _mockAccountContext.Setup(x => x.GetSingle(_accountId))
+ .Returns(
+ () =>
+ {
+ DomainAccount domainAccount = new() { Id = _accountId };
+ if (createdUpdate != null)
+ {
+ domainAccount.TeamspeakIdentities = new() { 2 };
+ domainAccount.Email = "test@test.com";
+ }
+
+ return domainAccount;
+ }
+ );
+
+ DomainAccount result = await _subject.ExecuteAsync(new(_accountId, _teamspeakId, _confirmationCode));
+
+ result.TeamspeakIdentities.Single().Should().Be(2);
+ createdUpdate.Should().BeEquivalentTo(expectedUpdate);
+
+ _mockConfirmationCodeService.Verify(x => x.ClearConfirmationCodes(It.IsAny>()), Times.Never);
+ _mockEventBus.Verify(x => x.Send(It.Is(m => m.TeamspeakIdentities.Single() == 2)), Times.Once);
+ _mockNotificationsService.Verify(
+ x => x.SendTeamspeakNotification(
+ It.Is>(m => m.Single() == 2),
+ "This teamspeak identity has been linked to the account with email 'test@test.com'\nIf this was not done by you, please contact an admin"
+ ),
+ Times.Once
+ );
+ _mockLogger.Verify(x => x.LogAudit($"Teamspeak ID {_teamspeakId} added for {_accountId}", null), Times.Once);
+ }
+
+ [Fact]
+ public void When_connecting_teamspeak_id_and_code_is_null()
+ {
+ _mockAccountContext.Setup(x => x.GetSingle(_accountId)).Returns(new DomainAccount());
+ _mockConfirmationCodeService.Setup(x => x.GetConfirmationCodeValue(_confirmationCode)).ReturnsAsync((string) null);
+
+ Func act = async () => await _subject.ExecuteAsync(new(_accountId, _teamspeakId, _confirmationCode));
+
+ act.Should().ThrowAsync().WithMessageAndStatusCode("Confirmation code was invalid or expired. Please try again", 400);
+ _mockConfirmationCodeService.Verify(x => x.ClearConfirmationCodes(It.Is>(m => m(new() { Value = _teamspeakId }))), Times.Once);
+ }
+ }
+}
diff --git a/Tests/UKSF.Api.Personnel.Tests/DependencyInjectionTests.cs b/Tests/UKSF.Api.Personnel.Tests/DependencyInjectionTests.cs
new file mode 100644
index 00000000..172475de
--- /dev/null
+++ b/Tests/UKSF.Api.Personnel.Tests/DependencyInjectionTests.cs
@@ -0,0 +1,81 @@
+using FluentAssertions;
+using Microsoft.Extensions.DependencyInjection;
+using UKSF.Api.Admin;
+using UKSF.Api.Personnel.Controllers;
+using UKSF.Api.Personnel.EventHandlers;
+using UKSF.Api.Personnel.ScheduledActions;
+using UKSF.Api.Tests.Common;
+using Xunit;
+
+namespace UKSF.Api.Personnel.Tests
+{
+ public class DependencyInjectionTests : DependencyInjectionTestsBase
+ {
+ public DependencyInjectionTests()
+ {
+ Services.AddUksfAdmin();
+ Services.AddUksfPersonnel();
+ }
+
+ [Fact]
+ public void When_resolving_controllers()
+ {
+ Services.AddTransient();
+ Services.AddTransient();
+ Services.AddTransient();
+ Services.AddTransient();
+ Services.AddTransient();
+ Services.AddTransient();
+ Services.AddTransient();
+ Services.AddTransient();
+ Services.AddTransient();
+ Services.AddTransient();
+ Services.AddTransient();
+ Services.AddTransient();
+ Services.AddTransient();
+ Services.AddTransient();
+ Services.AddTransient();
+ ServiceProvider serviceProvider = Services.BuildServiceProvider();
+
+ serviceProvider.GetRequiredService().Should().NotBeNull();
+ serviceProvider.GetRequiredService().Should().NotBeNull();
+ serviceProvider.GetRequiredService().Should().NotBeNull();
+ serviceProvider.GetRequiredService().Should().NotBeNull();
+ serviceProvider.GetRequiredService().Should().NotBeNull();
+ serviceProvider.GetRequiredService().Should().NotBeNull();
+ serviceProvider.GetRequiredService().Should().NotBeNull();
+ serviceProvider.GetRequiredService().Should().NotBeNull();
+ serviceProvider.GetRequiredService().Should().NotBeNull();
+ serviceProvider.GetRequiredService().Should().NotBeNull();
+ serviceProvider.GetRequiredService().Should().NotBeNull();
+ serviceProvider.GetRequiredService().Should().NotBeNull();
+ serviceProvider.GetRequiredService().Should().NotBeNull();
+ serviceProvider.GetRequiredService().Should().NotBeNull();
+ serviceProvider.GetRequiredService().Should().NotBeNull();
+ }
+
+ [Fact]
+ public void When_resolving_event_handlers()
+ {
+ Services.AddTransient();
+ Services.AddTransient();
+ Services.AddTransient();
+ ServiceProvider serviceProvider = Services.BuildServiceProvider();
+
+ serviceProvider.GetRequiredService().Should().NotBeNull();
+ serviceProvider.GetRequiredService().Should().NotBeNull();
+ serviceProvider.GetRequiredService().Should().NotBeNull();
+ }
+
+ [Fact]
+ public void When_resolving_scheduled_actions()
+ {
+ Services.AddTransient();
+ Services.AddTransient();
+ ServiceProvider serviceProvider = Services.BuildServiceProvider();
+
+ serviceProvider.GetRequiredService().Should().NotBeNull();
+ serviceProvider.GetRequiredService().Should().NotBeNull();
+ }
+ }
+}
diff --git a/Tests/UKSF.Api.Personnel.Tests/Mappers/AccountMapperTests.cs b/Tests/UKSF.Api.Personnel.Tests/Mappers/AccountMapperTests.cs
new file mode 100644
index 00000000..f02ec4cc
--- /dev/null
+++ b/Tests/UKSF.Api.Personnel.Tests/Mappers/AccountMapperTests.cs
@@ -0,0 +1,56 @@
+using System;
+using FluentAssertions;
+using MongoDB.Bson;
+using Moq;
+using UKSF.Api.Personnel.Mappers;
+using UKSF.Api.Personnel.Models;
+using UKSF.Api.Personnel.Services;
+using Xunit;
+
+namespace UKSF.Api.Personnel.Tests.Mappers
+{
+ public class AccountMapperTests
+ {
+ private readonly Mock _mockDisplayNameService;
+ private readonly AccountMapper _subject;
+
+ public AccountMapperTests()
+ {
+ _mockDisplayNameService = new();
+
+ _subject = new(_mockDisplayNameService.Object);
+ }
+
+ [Fact]
+ public void ShouldCopyAccountCorrectly()
+ {
+ string id = ObjectId.GenerateNewId().ToString();
+ DateTime timestamp = DateTime.Now.AddDays(-1);
+ DomainAccount domainAccount = new()
+ {
+ Id = id,
+ Firstname = "Bob",
+ Lastname = "McTest",
+ MembershipState = MembershipState.MEMBER,
+ TeamspeakIdentities = new() { 4, 4 },
+ ServiceRecord = new() { new() { Occurence = "Test", Timestamp = timestamp } },
+ RolePreferences = new() { "Aviation" },
+ MilitaryExperience = false
+ };
+
+ _mockDisplayNameService.Setup(x => x.GetDisplayName(domainAccount)).Returns("Cdt.McTest.B");
+
+ Account subject = _subject.MapToAccount(domainAccount);
+
+ subject.Id.Should().Be(id);
+ subject.DisplayName.Should().Be("Cdt.McTest.B");
+ subject.Firstname.Should().Be("Bob");
+ subject.Lastname.Should().Be("McTest");
+ subject.MembershipState.Should().Be(MembershipState.MEMBER);
+ subject.TeamspeakIdentities.Should().NotBeEmpty().And.HaveCount(1).And.ContainInOrder(new[] { 4 });
+ subject.ServiceRecord.Should().NotBeEmpty().And.HaveCount(1).And.OnlyContain(x => x.Occurence == "Test" && x.Timestamp == timestamp);
+ subject.RolePreferences.Should().Contain("Aviation");
+ subject.MilitaryExperience.Should().BeFalse();
+ }
+ }
+}
diff --git a/Tests/UKSF.Api.Personnel.Tests/UKSF.Api.Personnel.Tests.csproj b/Tests/UKSF.Api.Personnel.Tests/UKSF.Api.Personnel.Tests.csproj
new file mode 100644
index 00000000..d715dc67
--- /dev/null
+++ b/Tests/UKSF.Api.Personnel.Tests/UKSF.Api.Personnel.Tests.csproj
@@ -0,0 +1,29 @@
+
+
+
+ net5.0
+
+ false
+
+
+
+
+
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+
+
+
+
+
+
+
+
diff --git a/Tests/UKSF.Api.Shared.Tests/UKSF.Api.Shared.Tests.csproj b/Tests/UKSF.Api.Shared.Tests/UKSF.Api.Shared.Tests.csproj
new file mode 100644
index 00000000..3ef59110
--- /dev/null
+++ b/Tests/UKSF.Api.Shared.Tests/UKSF.Api.Shared.Tests.csproj
@@ -0,0 +1,27 @@
+
+
+
+ net5.0
+
+ false
+
+
+
+
+
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+
+
+
+
+
+
diff --git a/Tests/UKSF.Api.Tests.Common/AssertionExtensions.cs b/Tests/UKSF.Api.Tests.Common/AssertionExtensions.cs
new file mode 100644
index 00000000..8f3149eb
--- /dev/null
+++ b/Tests/UKSF.Api.Tests.Common/AssertionExtensions.cs
@@ -0,0 +1,20 @@
+using System.Threading.Tasks;
+using FluentAssertions;
+using FluentAssertions.Specialized;
+using UKSF.Api.Shared.Exceptions;
+
+namespace UKSF.Api.Tests.Common
+{
+ public static class AssertionExtensions
+ {
+ public static async Task WithMessageAndStatusCode(this Task> task, string expectedWildcardPattern, int statusCode) where T : UksfException
+ {
+ (await task).WithMessage(expectedWildcardPattern).And.StatusCode.Should().Be(statusCode);
+ }
+
+ public static void WithMessageAndStatusCode(this ExceptionAssertions assertion, string expectedWildcardPattern, int statusCode) where T : UksfException
+ {
+ assertion.WithMessage(expectedWildcardPattern).And.StatusCode.Should().Be(statusCode);
+ }
+ }
+}
diff --git a/Tests/UKSF.Api.Tests.Common/DependencyInjectionTestsBase.cs b/Tests/UKSF.Api.Tests.Common/DependencyInjectionTestsBase.cs
new file mode 100644
index 00000000..e3031e3a
--- /dev/null
+++ b/Tests/UKSF.Api.Tests.Common/DependencyInjectionTestsBase.cs
@@ -0,0 +1,35 @@
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.DependencyInjection.Extensions;
+using Microsoft.Extensions.Hosting;
+using Microsoft.Extensions.Logging;
+using Moq;
+using UKSF.Api.Base;
+using UKSF.Api.Shared;
+
+namespace UKSF.Api.Tests.Common
+{
+ public class DependencyInjectionTestsBase
+ {
+ protected readonly IConfigurationRoot Configuration;
+ protected readonly IHostEnvironment HostEnvironment;
+ protected readonly ServiceCollection Services;
+
+ protected DependencyInjectionTestsBase()
+ {
+ Mock mockHostEnvironment = new();
+ mockHostEnvironment.Setup(x => x.EnvironmentName).Returns(Environments.Development);
+
+ Services = new();
+ Configuration = TestConfigurationProvider.GetTestConfiguration();
+ HostEnvironment = mockHostEnvironment.Object;
+
+ Services.TryAddTransient(typeof(ILogger<>), typeof(Logger<>));
+ Services.TryAddTransient(typeof(ILoggerFactory), typeof(LoggerFactory));
+ Services.AddSingleton(Configuration);
+
+ Services.AddUksfBase(Configuration, HostEnvironment);
+ Services.AddUksfShared();
+ }
+ }
+}
diff --git a/Tests/UKSF.Api.Tests.Common/ITestCachedDataService.cs b/Tests/UKSF.Api.Tests.Common/ITestCachedDataService.cs
new file mode 100644
index 00000000..79fd7dc9
--- /dev/null
+++ b/Tests/UKSF.Api.Tests.Common/ITestCachedDataService.cs
@@ -0,0 +1,6 @@
+using UKSF.Api.Shared.Context;
+
+namespace UKSF.Api.Tests.Common
+{
+ public interface ITestCachedContext : IMongoContext { }
+}
diff --git a/Tests/UKSF.Api.Tests.Common/ITestDataService.cs b/Tests/UKSF.Api.Tests.Common/ITestDataService.cs
new file mode 100644
index 00000000..43832a7c
--- /dev/null
+++ b/Tests/UKSF.Api.Tests.Common/ITestDataService.cs
@@ -0,0 +1,6 @@
+using UKSF.Api.Shared.Context;
+
+namespace UKSF.Api.Tests.Common
+{
+ public interface ITestContext : IMongoContext { }
+}
diff --git a/Tests/UKSF.Api.Tests.Common/TestCachedContext.cs b/Tests/UKSF.Api.Tests.Common/TestCachedContext.cs
new file mode 100644
index 00000000..27dd213f
--- /dev/null
+++ b/Tests/UKSF.Api.Tests.Common/TestCachedContext.cs
@@ -0,0 +1,11 @@
+using UKSF.Api.Base.Context;
+using UKSF.Api.Base.Events;
+using UKSF.Api.Shared.Context;
+
+namespace UKSF.Api.Tests.Common
+{
+ public class TestCachedContext : CachedMongoContext, ITestCachedContext
+ {
+ public TestCachedContext(IMongoCollectionFactory mongoCollectionFactory, IEventBus eventBus, string collectionName) : base(mongoCollectionFactory, eventBus, collectionName) { }
+ }
+}
diff --git a/Tests/UKSF.Api.Tests.Common/TestComplexDataModel.cs b/Tests/UKSF.Api.Tests.Common/TestComplexDataModel.cs
new file mode 100644
index 00000000..2b0e63e4
--- /dev/null
+++ b/Tests/UKSF.Api.Tests.Common/TestComplexDataModel.cs
@@ -0,0 +1,11 @@
+using System.Collections.Generic;
+
+namespace UKSF.Api.Tests.Common
+{
+ public class TestComplexDataModel : TestDataModel
+ {
+ public TestDataModel Data;
+ public List DataList;
+ public List List;
+ }
+}
diff --git a/Tests/UKSF.Api.Tests.Common/TestConfigurationProvider.cs b/Tests/UKSF.Api.Tests.Common/TestConfigurationProvider.cs
new file mode 100644
index 00000000..b4e947d4
--- /dev/null
+++ b/Tests/UKSF.Api.Tests.Common/TestConfigurationProvider.cs
@@ -0,0 +1,12 @@
+using Microsoft.Extensions.Configuration;
+
+namespace UKSF.Api.Tests.Common
+{
+ public static class TestConfigurationProvider
+ {
+ public static IConfigurationRoot GetTestConfiguration()
+ {
+ return new ConfigurationBuilder().AddJsonFile("appsettings.Tests.json").Build();
+ }
+ }
+}
diff --git a/Tests/UKSF.Api.Tests.Common/TestContext.cs b/Tests/UKSF.Api.Tests.Common/TestContext.cs
new file mode 100644
index 00000000..d628c26c
--- /dev/null
+++ b/Tests/UKSF.Api.Tests.Common/TestContext.cs
@@ -0,0 +1,11 @@
+using UKSF.Api.Base.Context;
+using UKSF.Api.Base.Events;
+using UKSF.Api.Shared.Context;
+
+namespace UKSF.Api.Tests.Common
+{
+ public class TestContext : MongoContext, ITestContext
+ {
+ public TestContext(IMongoCollectionFactory mongoCollectionFactory, IEventBus eventBus, string collectionName) : base(mongoCollectionFactory, eventBus, collectionName) { }
+ }
+}
diff --git a/Tests/UKSF.Api.Tests.Common/TestDataModel.cs b/Tests/UKSF.Api.Tests.Common/TestDataModel.cs
new file mode 100644
index 00000000..bb60a587
--- /dev/null
+++ b/Tests/UKSF.Api.Tests.Common/TestDataModel.cs
@@ -0,0 +1,12 @@
+using System.Collections.Generic;
+using UKSF.Api.Base.Models;
+
+namespace UKSF.Api.Tests.Common
+{
+ public class TestDataModel : MongoObject
+ {
+ public Dictionary Dictionary = new();
+ public string Name;
+ public List