From 85031de3c288cc0f072d6f2be441021bf1b60111 Mon Sep 17 00:00:00 2001 From: Leon Hoppe Date: Sun, 24 Nov 2024 12:40:51 +0100 Subject: [PATCH] Started creating tests for database module --- .../Data/DatabaseContext.cs | 11 ++ .../HopFrame.Database.Tests.csproj | 29 ++++ .../PermissionValidatorTests.cs | 57 +++++++ .../Repositories/GroupRepositoryTests.cs | 152 ++++++++++++++++++ .../Repositories/PermissionRepositoryTests.cs | 118 ++++++++++++++ .../Repositories/TokenRepositoryTests.cs | 89 ++++++++++ HopFrame.sln | 7 + HopFrame.sln.DotSettings.user | 19 ++- .../HopFrame.Database.csproj | 6 + 9 files changed, 487 insertions(+), 1 deletion(-) create mode 100644 HopFrame.Database.Tests/Data/DatabaseContext.cs create mode 100644 HopFrame.Database.Tests/HopFrame.Database.Tests.csproj create mode 100644 HopFrame.Database.Tests/PermissionValidatorTests.cs create mode 100644 HopFrame.Database.Tests/Repositories/GroupRepositoryTests.cs create mode 100644 HopFrame.Database.Tests/Repositories/PermissionRepositoryTests.cs create mode 100644 HopFrame.Database.Tests/Repositories/TokenRepositoryTests.cs diff --git a/HopFrame.Database.Tests/Data/DatabaseContext.cs b/HopFrame.Database.Tests/Data/DatabaseContext.cs new file mode 100644 index 0000000..7bc93de --- /dev/null +++ b/HopFrame.Database.Tests/Data/DatabaseContext.cs @@ -0,0 +1,11 @@ +using Microsoft.EntityFrameworkCore; + +namespace HopFrame.Database.Tests.Data; + +public class DatabaseContext : HopDbContextBase { + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { + base.OnConfiguring(optionsBuilder); + + optionsBuilder.UseInMemoryDatabase(Guid.NewGuid().ToString()); + } +} \ No newline at end of file diff --git a/HopFrame.Database.Tests/HopFrame.Database.Tests.csproj b/HopFrame.Database.Tests/HopFrame.Database.Tests.csproj new file mode 100644 index 0000000..5246200 --- /dev/null +++ b/HopFrame.Database.Tests/HopFrame.Database.Tests.csproj @@ -0,0 +1,29 @@ + + + + net8.0 + enable + enable + + false + true + + + + + + + + + + + + + + + + + + + + diff --git a/HopFrame.Database.Tests/PermissionValidatorTests.cs b/HopFrame.Database.Tests/PermissionValidatorTests.cs new file mode 100644 index 0000000..9d858f8 --- /dev/null +++ b/HopFrame.Database.Tests/PermissionValidatorTests.cs @@ -0,0 +1,57 @@ +namespace HopFrame.Database.Tests; + +public class PermissionValidatorTests { + + [Fact] + public void IncludesPermission_Returns_True_For_ExactPermission() { + // Arrange + var permissions = new [] { "test.permission", "test.permission.exact" }; + var permission = "test.permission.exact"; + + // Act + var hasPermission = PermissionValidator.IncludesPermission(permission, permissions); + + // Assert + Assert.True(hasPermission); + } + + [Fact] + public void IncludesPermission_Returns_True_For_GroupPermission() { + // Arrange + var permissions = new [] { "test.permission.*", "test.permission.exact" }; + var permission = "test.permission.exact.other"; + + // Act + var hasPermission = PermissionValidator.IncludesPermission(permission, permissions); + + // Assert + Assert.True(hasPermission); + } + + [Fact] + public void IncludesPermission_Returns_True_For_StarPermission() { + // Arrange + var permissions = new [] { "test.permission", "test.permission.exact", "*" }; + var permission = "test.permission.exact.other"; + + // Act + var hasPermission = PermissionValidator.IncludesPermission(permission, permissions); + + // Assert + Assert.True(hasPermission); + } + + [Fact] + public void IncludesPermission_Returns_False() { + // Arrange + var permissions = new [] { "test.permission", "test.permission.exact" }; + var permission = "test.permission.exact.other"; + + // Act + var hasPermission = PermissionValidator.IncludesPermission(permission, permissions); + + // Assert + Assert.False(hasPermission); + } + +} \ No newline at end of file diff --git a/HopFrame.Database.Tests/Repositories/GroupRepositoryTests.cs b/HopFrame.Database.Tests/Repositories/GroupRepositoryTests.cs new file mode 100644 index 0000000..84270e0 --- /dev/null +++ b/HopFrame.Database.Tests/Repositories/GroupRepositoryTests.cs @@ -0,0 +1,152 @@ +using HopFrame.Database.Models; +using HopFrame.Database.Repositories; +using HopFrame.Database.Repositories.Implementation; +using HopFrame.Database.Tests.Data; + +namespace HopFrame.Database.Tests.Repositories; + +public class GroupRepositoryTests { + + private async Task<(DatabaseContext, IGroupRepository)> SetupEnvironment(int count = 5) { + var context = new DatabaseContext(); + var repo = new GroupRepository(context); + + for (int i = 0; i < count; i++) { + await context.Groups.AddAsync(new() { + Name = Guid.NewGuid().ToString() + }); + } + await context.SaveChangesAsync(); + + return (context, repo); + } + + [Fact] + public async Task GetPermissionGroups_Returns_AllPermissionGroups() { + // Arrange + var count = 5; + var (context, repo) = await SetupEnvironment(count); + + // Act + var groups = await repo.GetPermissionGroups(); + + // Assert + Assert.Equal(count, groups.Count); + } + + [Fact] + public async Task GetDefaultGroups_Returns_OnlyDefaultGroups() { + // Arrange + var (context, repo) = await SetupEnvironment(); + await context.Groups.AddAsync(new () { + Name = Guid.NewGuid().ToString(), + IsDefaultGroup = true + }); + await context.SaveChangesAsync(); + + // Act + var groups = await repo.GetDefaultGroups(); + + // Assert + Assert.Single(groups); + Assert.True(groups[0].IsDefaultGroup); + } + + [Fact] + public async Task GetUserGroups_Returns_OnlyUserGroups() { + // Arrange + var (context, repo) = await SetupEnvironment(); + await context.Groups.AddAsync(new () { + Name = "group.user_should_have_these", + }); + var user = new User { + Id = Guid.NewGuid(), + Email = "", + Username = "", + Password = "" + }; + user.Permissions = new() { + new() { + User = user, + PermissionName = "group.user_should_have_these" + } + }; + await context.Users.AddAsync(user); + await context.SaveChangesAsync(); + + // Act + var groups = await repo.GetUserGroups(user); + + // Assert + Assert.Single(groups); + Assert.Equal("group.user_should_have_these", groups[0].Name); + } + + [Fact] + public async Task GetPermissionGroup_Returns_OnlyOnePermissionGroup() { + // Arrange + var (context, repo) = await SetupEnvironment(); + await context.Groups.AddAsync(new () { + Name = "group.return" + }); + await context.SaveChangesAsync(); + + // Act + var group = await repo.GetPermissionGroup("group.return"); + + // Assert + Assert.NotNull(group); + Assert.Equal("group.return", group.Name); + } + + [Fact] + public async Task EditPermissionGroup_Should_EditOnePermissionGroup() { + // Arrange + var (context, repo) = await SetupEnvironment(); + var groupToEdit = new PermissionGroup { + Name = "group.edit" + }; + await context.Groups.AddAsync(groupToEdit); + await context.SaveChangesAsync(); + + // Act + groupToEdit.Description = "This description was edited"; + await repo.EditPermissionGroup(groupToEdit); + + // Assert + var group = context.Groups.SingleOrDefault(g => g.Name == "group.edit"); + Assert.NotNull(group); + Assert.Equal("This description was edited", group.Description); + } + + [Fact] + public async Task CreatePermissionGroup_Should_AddOnePermissionGroup() { + // Arrange + var (context, repo) = await SetupEnvironment(0); + var group = new PermissionGroup { + Name = "group", + Description = "Group to add" + }; + + // Act + var result = await repo.CreatePermissionGroup(group); + + // Assert + Assert.Equal(group, result); + Assert.Single(context.Groups); + } + + [Fact] + public async Task DeletePermissionGroup_Should_DeleteOnePermissionGroup() { + // Arrange + var count = 5; + var (context, repo) = await SetupEnvironment(count); + + // Act + await repo.DeletePermissionGroup(context.Groups.First()); + + // Assert + Assert.Equal(count - 1, context.Groups.Count()); + } + +} \ No newline at end of file diff --git a/HopFrame.Database.Tests/Repositories/PermissionRepositoryTests.cs b/HopFrame.Database.Tests/Repositories/PermissionRepositoryTests.cs new file mode 100644 index 0000000..52a9ef7 --- /dev/null +++ b/HopFrame.Database.Tests/Repositories/PermissionRepositoryTests.cs @@ -0,0 +1,118 @@ +using HopFrame.Database.Models; +using HopFrame.Database.Repositories; +using HopFrame.Database.Repositories.Implementation; +using HopFrame.Database.Tests.Data; +using Microsoft.EntityFrameworkCore; + +namespace HopFrame.Database.Tests.Repositories; + +public class PermissionRepositoryTests { + + private async Task<(DatabaseContext, IPermissionRepository)> SetupEnvironment(int count = 5) { + var context = new DatabaseContext(); + var repo = new PermissionRepository(context, new GroupRepository(context)); + + for (int i = 0; i < count; i++) { + await context.Permissions.AddAsync(new () { + PermissionName = Guid.NewGuid().ToString(), + User = CreateTestUser() + }); + } + await context.SaveChangesAsync(); + + return (context, repo); + } + + private User CreateTestUser() => new () { + Username = "", + Email = "", + Password = "" + }; + + [Fact] + public async Task HasPermission_Returns_True() { + // Arrange + var (context, repo) = await SetupEnvironment(); + var user = CreateTestUser(); + await context.Permissions.AddAsync(new() { + PermissionName = "*", + User = user + }); + await context.SaveChangesAsync(); + + // Act + var hasPermission = await repo.HasPermission(user, "*"); + + // Assert + Assert.True(hasPermission); + } + + [Fact] + public async Task AddPermission_Should_AddOnePermission() { + // Arrange + var (context, repo) = await SetupEnvironment(); + var user = CreateTestUser(); + + // Act + var result = await repo.AddPermission(user, "test.permission"); + + // Assert + Assert.NotNull(result); + Assert.Single(context.Permissions + .Include(p => p.User) + .Where(p => p.User.Id == user.Id && p.PermissionName == "test.permission")); + } + + [Fact] + public async Task RemovePermission_Should_RemoveOnePermission() { + // Arrange + var (context, repo) = await SetupEnvironment(); + var user = CreateTestUser(); + await context.Permissions.AddAsync(new() { + PermissionName = "test.permission", + User = user + }); + await context.SaveChangesAsync(); + + // Act + await repo.RemovePermission(user, "test.permission"); + + // Assert + Assert.Empty(context.Permissions + .Include(p => p.User) + .Where(p => p.User.Id == user.Id && p.PermissionName == "test.permission")); + } + + [Fact] + public async Task GetFullPermissions_Return_AllPermissions_Including_Inherited() { + // Arrange + var (context, repo) = await SetupEnvironment(); + var user = CreateTestUser(); + var group = new PermissionGroup { + Name = "group.admin" + }; + await context.Permissions.AddRangeAsync(new List { + new() { + PermissionName = "test.permission.inherited", + Group = group + }, + new() { + PermissionName = "test.permission", + User = user + }, + new() { + PermissionName = "group.admin", + User = user + } + }); + await context.SaveChangesAsync(); + + // Act + var perms = await repo.GetFullPermissions(user); + + // Assert + Assert.NotNull(perms); + Assert.Equal(3, perms.Count); + } + +} \ No newline at end of file diff --git a/HopFrame.Database.Tests/Repositories/TokenRepositoryTests.cs b/HopFrame.Database.Tests/Repositories/TokenRepositoryTests.cs new file mode 100644 index 0000000..97e382a --- /dev/null +++ b/HopFrame.Database.Tests/Repositories/TokenRepositoryTests.cs @@ -0,0 +1,89 @@ +using HopFrame.Database.Models; +using HopFrame.Database.Repositories; +using HopFrame.Database.Repositories.Implementation; +using HopFrame.Database.Tests.Data; +using Microsoft.EntityFrameworkCore; + +namespace HopFrame.Database.Tests.Repositories; + +public class TokenRepositoryTests { + + private async Task<(DatabaseContext, ITokenRepository)> SetupEnvironment(int count = 5) { + var context = new DatabaseContext(); + var repo = new TokenRepository(context); + + for (int i = 0; i < count; i++) { + await context.Tokens.AddAsync(new() { + Content = Guid.NewGuid(), + Owner = CreateTestUser(), + Type = Token.AccessTokenType + }); + } + await context.SaveChangesAsync(); + + return (context, repo); + } + + private User CreateTestUser() => new () { + Username = "", + Email = "", + Password = "" + }; + + [Fact] + public async Task GetToken_Return_CorrectToken() { + // Arrange + var (context, repo) = await SetupEnvironment(); + var token = context.Tokens.First(); + + // Act + var result = await repo.GetToken(token.Content.ToString()); + + // Assert + Assert.Equal(token, result); + } + + [Fact] + public async Task CreateToken_Should_CreateOneToken() { + // Arrange + var (context, repo) = await SetupEnvironment(0); + + // Act + var result = await repo.CreateToken(Token.AccessTokenType, CreateTestUser()); + + // Assert + Assert.NotEmpty(context.Tokens); + Assert.Equal(result, context.Tokens.First()); + } + + [Fact] + public async Task DeleteUserTokens_Should_DeleteOnlyUserTokens() { + // Arrange + var dummyCount = 5; + var (context, repo) = await SetupEnvironment(dummyCount); + var user = CreateTestUser(); + await context.Tokens.AddRangeAsync(new List { + new() { + Content = Guid.NewGuid(), + Owner = user, + Type = Token.AccessTokenType + }, + new() { + Content = Guid.NewGuid(), + Owner = user, + Type = Token.RefreshTokenType + } + }); + await context.SaveChangesAsync(); + + // Act + await repo.DeleteUserTokens(user); + + // Assert + Assert.Equal(dummyCount, context.Tokens.Count()); + Assert.Empty(context.Tokens + .Include(t => t.Owner) + .Where(t => t.Owner == user)); + } + +} \ No newline at end of file diff --git a/HopFrame.sln b/HopFrame.sln index 269b7be..9177f94 100644 --- a/HopFrame.sln +++ b/HopFrame.sln @@ -20,6 +20,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Testing", "Testing", "{EEA2 EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{1D98E5DE-CB8B-4C1C-A319-D49AC137441A}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HopFrame.Database.Tests", "HopFrame.Database.Tests\HopFrame.Database.Tests.csproj", "{1CAAC943-B8FE-48DD-9712-92699647DE18}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -54,6 +56,10 @@ Global {02D9F10A-664A-4EF7-BF19-310C26FF4DEB}.Debug|Any CPU.Build.0 = Debug|Any CPU {02D9F10A-664A-4EF7-BF19-310C26FF4DEB}.Release|Any CPU.ActiveCfg = Release|Any CPU {02D9F10A-664A-4EF7-BF19-310C26FF4DEB}.Release|Any CPU.Build.0 = Release|Any CPU + {1CAAC943-B8FE-48DD-9712-92699647DE18}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1CAAC943-B8FE-48DD-9712-92699647DE18}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1CAAC943-B8FE-48DD-9712-92699647DE18}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1CAAC943-B8FE-48DD-9712-92699647DE18}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(NestedProjects) = preSolution {1E821490-AEDC-4F55-B758-52F4FADAB53A} = {64EDCBED-A84F-4936-8697-78DC43CB2427} @@ -63,5 +69,6 @@ Global {02D9F10A-664A-4EF7-BF19-310C26FF4DEB} = {64EDCBED-A84F-4936-8697-78DC43CB2427} {8F983A37-63CF-48D5-988D-58B78EF8AECD} = {EEA20D27-D471-44AF-A287-C0E068D93182} {921159CE-AF75-44C3-A3F9-6B9B1A4E85CF} = {EEA20D27-D471-44AF-A287-C0E068D93182} + {1CAAC943-B8FE-48DD-9712-92699647DE18} = {1D98E5DE-CB8B-4C1C-A319-D49AC137441A} EndGlobalSection EndGlobal diff --git a/HopFrame.sln.DotSettings.user b/HopFrame.sln.DotSettings.user index a38eed3..1798b6e 100644 --- a/HopFrame.sln.DotSettings.user +++ b/HopFrame.sln.DotSettings.user @@ -5,4 +5,21 @@ <AssemblyExplorer> <Assembly Path="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\7.0.16\ref\net7.0\System.ComponentModel.Annotations.dll" /> <Assembly Path="C:\Users\Remote\.nuget\packages\blazorstrap\5.2.100.61524\lib\net7.0\BlazorStrap.dll" /> -</AssemblyExplorer> \ No newline at end of file +</AssemblyExplorer> + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/HopFrame.Database/HopFrame.Database.csproj b/src/HopFrame.Database/HopFrame.Database.csproj index de55cd5..621c7b9 100644 --- a/src/HopFrame.Database/HopFrame.Database.csproj +++ b/src/HopFrame.Database/HopFrame.Database.csproj @@ -22,4 +22,10 @@ + + + <_Parameter1>HopFrame.Database.Tests + + +