diff --git a/.idea/.idea.HopFrame/.idea/workspace.xml b/.idea/.idea.HopFrame/.idea/workspace.xml
index be4a925..09e7fe9 100644
--- a/.idea/.idea.HopFrame/.idea/workspace.xml
+++ b/.idea/.idea.HopFrame/.idea/workspace.xml
@@ -10,20 +10,32 @@
-
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -168,7 +180,8 @@
-
+
+
@@ -306,7 +319,15 @@
1737212497960
-
+
+
+ 1737285123218
+
+
+
+ 1737285123218
+
+
@@ -321,52 +342,33 @@
-
+
-
-
+
+
-
-
-
+
+
+
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
@@ -393,6 +395,7 @@
-
+
+
\ No newline at end of file
diff --git a/HopFrame.sln b/HopFrame.sln
index 10bd3c7..877f6af 100644
--- a/HopFrame.sln
+++ b/HopFrame.sln
@@ -12,7 +12,9 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HopFrame.Testing", "testing
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{141928CB-5977-4285-A986-5BD785F2883C}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HopFrame.Core.Tests", "tests\HopFrame.Core.Tests\HopFrame.Core.Tests.csproj", "{2E2D29E0-53FA-462D-B4D2-4678CD106E29}"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HopFrame.Tests.Core", "tests\HopFrame.Tests.Core\HopFrame.Tests.Core.csproj", "{2E2D29E0-53FA-462D-B4D2-4678CD106E29}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HopFrame.Tests.Web", "tests\HopFrame.Tests.Web\HopFrame.Tests.Web.csproj", "{7AB4F4FF-E938-4A40-A7EB-7B2063262896}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -24,6 +26,7 @@ Global
{8E59F398-184A-47C9-AAA2-3E0FFD775ABF} = {7E4AAFB3-9762-4F42-86DF-5A3194FDC243}
{58490069-51DF-454C-8B54-7FB7D4BDFF81} = {9EB7FDBD-49C2-4872-9666-6F7AEBA541B2}
{2E2D29E0-53FA-462D-B4D2-4678CD106E29} = {141928CB-5977-4285-A986-5BD785F2883C}
+ {7AB4F4FF-E938-4A40-A7EB-7B2063262896} = {141928CB-5977-4285-A986-5BD785F2883C}
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{4BFE21C2-EAAC-4662-8B97-500836651B2A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
@@ -42,5 +45,9 @@ Global
{2E2D29E0-53FA-462D-B4D2-4678CD106E29}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2E2D29E0-53FA-462D-B4D2-4678CD106E29}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2E2D29E0-53FA-462D-B4D2-4678CD106E29}.Release|Any CPU.Build.0 = Release|Any CPU
+ {7AB4F4FF-E938-4A40-A7EB-7B2063262896}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {7AB4F4FF-E938-4A40-A7EB-7B2063262896}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {7AB4F4FF-E938-4A40-A7EB-7B2063262896}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {7AB4F4FF-E938-4A40-A7EB-7B2063262896}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal
diff --git a/src/HopFrame.Core/HopFrame.Core.csproj b/src/HopFrame.Core/HopFrame.Core.csproj
index d29affa..4056565 100644
--- a/src/HopFrame.Core/HopFrame.Core.csproj
+++ b/src/HopFrame.Core/HopFrame.Core.csproj
@@ -12,7 +12,7 @@
- <_Parameter1>HopFrame.Core.Tests
+ <_Parameter1>HopFrame.Tests.Core
diff --git a/tests/HopFrame.Core.Tests/Config/DbContextConfiguratorTests.cs b/tests/HopFrame.Tests.Core/Config/DbContextConfiguratorTests.cs
similarity index 93%
rename from tests/HopFrame.Core.Tests/Config/DbContextConfiguratorTests.cs
rename to tests/HopFrame.Tests.Core/Config/DbContextConfiguratorTests.cs
index 568ec13..ce0fd1c 100644
--- a/tests/HopFrame.Core.Tests/Config/DbContextConfiguratorTests.cs
+++ b/tests/HopFrame.Tests.Core/Config/DbContextConfiguratorTests.cs
@@ -1,8 +1,8 @@
using HopFrame.Core.Config;
-using HopFrame.Core.Tests.Models;
+using HopFrame.Tests.Core.Models;
using Moq;
-namespace HopFrame.Core.Tests.Config;
+namespace HopFrame.Tests.Core.Config;
public class DbContextConfiguratorTests {
[Fact]
diff --git a/tests/HopFrame.Core.Tests/Config/HopFrameConfiguratorTests.cs b/tests/HopFrame.Tests.Core/Config/HopFrameConfiguratorTests.cs
similarity index 96%
rename from tests/HopFrame.Core.Tests/Config/HopFrameConfiguratorTests.cs
rename to tests/HopFrame.Tests.Core/Config/HopFrameConfiguratorTests.cs
index a9ad5a2..4026f41 100644
--- a/tests/HopFrame.Core.Tests/Config/HopFrameConfiguratorTests.cs
+++ b/tests/HopFrame.Tests.Core/Config/HopFrameConfiguratorTests.cs
@@ -1,7 +1,7 @@
using HopFrame.Core.Config;
-using HopFrame.Core.Tests.Models;
+using HopFrame.Tests.Core.Models;
-namespace HopFrame.Core.Tests.Config;
+namespace HopFrame.Tests.Core.Config;
public class HopFrameConfiguratorTests {
[Fact]
diff --git a/tests/HopFrame.Core.Tests/Config/PropertyConfiguratorTests.cs b/tests/HopFrame.Tests.Core/Config/PropertyConfiguratorTests.cs
similarity index 99%
rename from tests/HopFrame.Core.Tests/Config/PropertyConfiguratorTests.cs
rename to tests/HopFrame.Tests.Core/Config/PropertyConfiguratorTests.cs
index a0e5ce1..312d77a 100644
--- a/tests/HopFrame.Core.Tests/Config/PropertyConfiguratorTests.cs
+++ b/tests/HopFrame.Tests.Core/Config/PropertyConfiguratorTests.cs
@@ -1,8 +1,8 @@
using System.Linq.Expressions;
using HopFrame.Core.Config;
-using HopFrame.Core.Tests.Models;
+using HopFrame.Tests.Core.Models;
-namespace HopFrame.Core.Tests.Config;
+namespace HopFrame.Tests.Core.Config;
public class PropertyConfiguratorTests {
[Fact]
diff --git a/tests/HopFrame.Core.Tests/Config/TableConfiguratorTests.cs b/tests/HopFrame.Tests.Core/Config/TableConfiguratorTests.cs
similarity index 99%
rename from tests/HopFrame.Core.Tests/Config/TableConfiguratorTests.cs
rename to tests/HopFrame.Tests.Core/Config/TableConfiguratorTests.cs
index f7454ce..10bbc3d 100644
--- a/tests/HopFrame.Core.Tests/Config/TableConfiguratorTests.cs
+++ b/tests/HopFrame.Tests.Core/Config/TableConfiguratorTests.cs
@@ -1,8 +1,8 @@
using System.Linq.Expressions;
using HopFrame.Core.Config;
-using HopFrame.Core.Tests.Models;
+using HopFrame.Tests.Core.Models;
-namespace HopFrame.Core.Tests.Config;
+namespace HopFrame.Tests.Core.Config;
public class TableConfiguratorTests {
[Fact]
diff --git a/tests/HopFrame.Core.Tests/HopFrame.Core.Tests.csproj b/tests/HopFrame.Tests.Core/HopFrame.Tests.Core.csproj
similarity index 100%
rename from tests/HopFrame.Core.Tests/HopFrame.Core.Tests.csproj
rename to tests/HopFrame.Tests.Core/HopFrame.Tests.Core.csproj
diff --git a/tests/HopFrame.Core.Tests/Models/MockDbContext.cs b/tests/HopFrame.Tests.Core/Models/MockDbContext.cs
similarity index 90%
rename from tests/HopFrame.Core.Tests/Models/MockDbContext.cs
rename to tests/HopFrame.Tests.Core/Models/MockDbContext.cs
index 4666454..8f27aaf 100644
--- a/tests/HopFrame.Core.Tests/Models/MockDbContext.cs
+++ b/tests/HopFrame.Tests.Core/Models/MockDbContext.cs
@@ -1,6 +1,6 @@
using Microsoft.EntityFrameworkCore;
-namespace HopFrame.Core.Tests.Models;
+namespace HopFrame.Tests.Core.Models;
// A mock DbContext for testing purposes
public class MockDbContext : DbContext {
diff --git a/tests/HopFrame.Core.Tests/Models/MockModel.cs b/tests/HopFrame.Tests.Core/Models/MockModel.cs
similarity index 87%
rename from tests/HopFrame.Core.Tests/Models/MockModel.cs
rename to tests/HopFrame.Tests.Core/Models/MockModel.cs
index 2a340b1..9568dda 100644
--- a/tests/HopFrame.Core.Tests/Models/MockModel.cs
+++ b/tests/HopFrame.Tests.Core/Models/MockModel.cs
@@ -1,6 +1,6 @@
using System.ComponentModel.DataAnnotations.Schema;
-namespace HopFrame.Core.Tests.Models;
+namespace HopFrame.Tests.Core.Models;
// A mock model for testing purposes
public class MockModel {
diff --git a/tests/HopFrame.Core.Tests/Models/MockModel2.cs b/tests/HopFrame.Tests.Core/Models/MockModel2.cs
similarity index 88%
rename from tests/HopFrame.Core.Tests/Models/MockModel2.cs
rename to tests/HopFrame.Tests.Core/Models/MockModel2.cs
index c6b5b12..f45288b 100644
--- a/tests/HopFrame.Core.Tests/Models/MockModel2.cs
+++ b/tests/HopFrame.Tests.Core/Models/MockModel2.cs
@@ -1,7 +1,7 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
-namespace HopFrame.Core.Tests.Models;
+namespace HopFrame.Tests.Core.Models;
public class MockModel2 {
[Key]
diff --git a/tests/HopFrame.Core.Tests/Models/QueryProvider.cs b/tests/HopFrame.Tests.Core/Models/QueryProvider.cs
similarity index 99%
rename from tests/HopFrame.Core.Tests/Models/QueryProvider.cs
rename to tests/HopFrame.Tests.Core/Models/QueryProvider.cs
index 65b0127..6ec277d 100644
--- a/tests/HopFrame.Core.Tests/Models/QueryProvider.cs
+++ b/tests/HopFrame.Tests.Core/Models/QueryProvider.cs
@@ -1,7 +1,7 @@
using System.Linq.Expressions;
using Microsoft.EntityFrameworkCore.Query;
-namespace HopFrame.Core.Tests.Models;
+namespace HopFrame.Tests.Core.Models;
// A mock implementation for async query provider
internal class TestAsyncQueryProvider : IAsyncQueryProvider {
diff --git a/tests/HopFrame.Core.Tests/Services/ContextExplorerTests.cs b/tests/HopFrame.Tests.Core/Services/ContextExplorerTests.cs
similarity index 99%
rename from tests/HopFrame.Core.Tests/Services/ContextExplorerTests.cs
rename to tests/HopFrame.Tests.Core/Services/ContextExplorerTests.cs
index d24315f..c0b54a1 100644
--- a/tests/HopFrame.Core.Tests/Services/ContextExplorerTests.cs
+++ b/tests/HopFrame.Tests.Core/Services/ContextExplorerTests.cs
@@ -1,10 +1,10 @@
using HopFrame.Core.Config;
using HopFrame.Core.Services.Implementations;
-using HopFrame.Core.Tests.Models;
+using HopFrame.Tests.Core.Models;
using Microsoft.Extensions.Logging;
using Moq;
-namespace HopFrame.Core.Tests.Services;
+namespace HopFrame.Tests.Core.Services;
public class ContextExplorerTests {
[Fact]
diff --git a/tests/HopFrame.Core.Tests/Services/DefaultAuthHandlerTests.cs b/tests/HopFrame.Tests.Core/Services/DefaultAuthHandlerTests.cs
similarity index 96%
rename from tests/HopFrame.Core.Tests/Services/DefaultAuthHandlerTests.cs
rename to tests/HopFrame.Tests.Core/Services/DefaultAuthHandlerTests.cs
index f93d58b..aa37b8d 100644
--- a/tests/HopFrame.Core.Tests/Services/DefaultAuthHandlerTests.cs
+++ b/tests/HopFrame.Tests.Core/Services/DefaultAuthHandlerTests.cs
@@ -1,6 +1,6 @@
using HopFrame.Core.Services.Implementations;
-namespace HopFrame.Core.Tests.Services;
+namespace HopFrame.Tests.Core.Services;
public class DefaultAuthHandlerTests {
[Fact]
diff --git a/tests/HopFrame.Core.Tests/Services/DisplayPropertyTests.cs b/tests/HopFrame.Tests.Core/Services/DisplayPropertyTests.cs
similarity index 98%
rename from tests/HopFrame.Core.Tests/Services/DisplayPropertyTests.cs
rename to tests/HopFrame.Tests.Core/Services/DisplayPropertyTests.cs
index d6168ff..d987283 100644
--- a/tests/HopFrame.Core.Tests/Services/DisplayPropertyTests.cs
+++ b/tests/HopFrame.Tests.Core/Services/DisplayPropertyTests.cs
@@ -1,11 +1,11 @@
using HopFrame.Core.Config;
using HopFrame.Core.Services;
using HopFrame.Core.Services.Implementations;
-using HopFrame.Core.Tests.Models;
+using HopFrame.Tests.Core.Models;
using Microsoft.EntityFrameworkCore;
using Moq;
-namespace HopFrame.Core.Tests.Services;
+namespace HopFrame.Tests.Core.Services;
public class DisplayPropertyTests {
private readonly Mock _providerMock;
diff --git a/tests/HopFrame.Core.Tests/Services/TableManagerTests.cs b/tests/HopFrame.Tests.Core/Services/TableManagerTests.cs
similarity index 99%
rename from tests/HopFrame.Core.Tests/Services/TableManagerTests.cs
rename to tests/HopFrame.Tests.Core/Services/TableManagerTests.cs
index e2d85bb..2d5dc2c 100644
--- a/tests/HopFrame.Core.Tests/Services/TableManagerTests.cs
+++ b/tests/HopFrame.Tests.Core/Services/TableManagerTests.cs
@@ -3,11 +3,11 @@
using HopFrame.Core.Config;
using HopFrame.Core.Services;
using HopFrame.Core.Services.Implementations;
-using HopFrame.Core.Tests.Models;
+using HopFrame.Tests.Core.Models;
using Microsoft.EntityFrameworkCore;
using Moq;
-namespace HopFrame.Core.Tests.Services;
+namespace HopFrame.Tests.Core.Services;
public class TableManagerTests {
private Mock CreateMockDbContext(List data) where TModel : class {
diff --git a/tests/HopFrame.Tests.Web/Components/Dialogs/HopFrameEditorTests.cs b/tests/HopFrame.Tests.Web/Components/Dialogs/HopFrameEditorTests.cs
new file mode 100644
index 0000000..5aee780
--- /dev/null
+++ b/tests/HopFrame.Tests.Web/Components/Dialogs/HopFrameEditorTests.cs
@@ -0,0 +1,63 @@
+using Bunit;
+using HopFrame.Core.Config;
+using HopFrame.Core.Services;
+using HopFrame.Tests.Web.Models;
+using HopFrame.Web;
+using HopFrame.Web.Components.Dialogs;
+using HopFrame.Web.Models;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.FluentUI.AspNetCore.Components;
+using Moq;
+
+namespace HopFrame.Tests.Web.Components.Dialogs;
+
+public class HopFrameEditorTests : TestContext {
+ [Fact]
+ public void Renders_Properties_Correctly() {
+ // Arrange
+ var contextExplorerMock = new Mock();
+ var authHandlerMock = new Mock();
+ var dialogServiceMock = new Mock();
+ var toastServiceMock = new Mock();
+ var serviceProviderMock = new Mock();
+ var contextConfig = new DbContextConfig(typeof(MyDbContext));
+ var tableConfig = new TableConfig(contextConfig, typeof(MyTable), "Table1", 0) {
+ DisplayName = "Table1",
+ ViewPolicy = "Policy1"
+ };
+ contextConfig.Tables.Add(tableConfig);
+ var config = new HopFrameConfig() {
+ Contexts = { contextConfig }
+ };
+
+ contextExplorerMock.Setup(e => e.GetTable("Table1")).Returns(tableConfig);
+ contextExplorerMock.Setup(e => e.GetTableManager("Table1")).Returns(Mock.Of());
+ authHandlerMock.Setup(h => h.IsAuthenticatedAsync(It.IsAny())).ReturnsAsync(true);
+
+ Services.AddHopFrame(config);
+ Services.AddSingleton(contextExplorerMock.Object);
+ Services.AddSingleton(authHandlerMock.Object);
+ Services.AddSingleton(dialogServiceMock.Object);
+ Services.AddSingleton(toastServiceMock.Object);
+ Services.AddSingleton(serviceProviderMock.Object);
+
+ JSInterop.Mode = JSRuntimeMode.Loose;
+
+ var dialogData = new EditorDialogData(tableConfig, new MyTable());
+ var dialog = new FluentDialog() {
+ Instance = new DialogInstance(typeof(HopFrameEditor), new DialogParameters(), dialogData)
+ };
+
+ // Act
+ var cut = RenderComponent(parameters => parameters
+ .Add(p => p.Content, dialogData)
+ .Add(p => p.Dialog, dialog));
+
+ // Assert
+ var dialogBody = cut.FindComponent();
+ Assert.NotNull(dialogBody);
+
+ var textFields = cut.FindComponents>();
+ Assert.Single(textFields);
+ }
+}
\ No newline at end of file
diff --git a/tests/HopFrame.Tests.Web/Components/Layout/HopFrameLayoutTests.cs b/tests/HopFrame.Tests.Web/Components/Layout/HopFrameLayoutTests.cs
new file mode 100644
index 0000000..62bb28a
--- /dev/null
+++ b/tests/HopFrame.Tests.Web/Components/Layout/HopFrameLayoutTests.cs
@@ -0,0 +1,74 @@
+using Bunit;
+using Bunit.TestDoubles;
+using HopFrame.Core.Config;
+using HopFrame.Core.Services;
+using HopFrame.Web;
+using HopFrame.Web.Components.Layout;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.FluentUI.AspNetCore.Components;
+using Moq;
+
+namespace HopFrame.Tests.Web.Components.Layout;
+
+public class HopFrameLayoutTests : TestContext {
+ [Fact]
+ public void Renders_HopFrameLayout_Components() {
+ // Arrange
+ var authHandlerMock = new Mock();
+ var config = new HopFrameConfig {
+ DisplayUserInfo = true,
+ BasePolicy = "SomePolicy",
+ LoginPageRewrite = "/login"
+ };
+
+ authHandlerMock.Setup(h => h.IsAuthenticatedAsync("SomePolicy"))
+ .ReturnsAsync(true);
+
+ Services.AddSingleton(authHandlerMock.Object);
+ Services.AddHopFrame(config);
+
+ JSInterop.Mode = JSRuntimeMode.Loose;
+
+ // Act
+ var cut = RenderComponent();
+
+ // Assert
+ var header = cut.FindComponent();
+ Assert.NotNull(header);
+
+ var navigation = cut.FindComponent();
+ Assert.NotNull(navigation);
+
+ var sideMenu = cut.FindComponent();
+ Assert.NotNull(sideMenu);
+
+ var footer = cut.FindComponent();
+ Assert.NotNull(footer);
+ }
+
+ [Fact]
+ public void Redirects_To_Login_When_Not_Authorized() {
+ // Arrange
+ var authHandlerMock = new Mock();
+ var navMock = new FakeNavigationManager(this);
+ var config = new HopFrameConfig {
+ DisplayUserInfo = true,
+ BasePolicy = "SomePolicy",
+ LoginPageRewrite = "/login"
+ };
+
+ authHandlerMock.Setup(h => h.IsAuthenticatedAsync("SomePolicy"))
+ .ReturnsAsync(false);
+
+ Services.AddSingleton(navMock);
+ Services.AddHopFrame(config);
+
+ JSInterop.Mode = JSRuntimeMode.Loose;
+
+ // Act
+ var cut = RenderComponent();
+
+ // Assert
+ // TODO: check if uri matches
+ }
+}
\ No newline at end of file
diff --git a/tests/HopFrame.Tests.Web/Components/Layout/HopFrameNavigationTests.cs b/tests/HopFrame.Tests.Web/Components/Layout/HopFrameNavigationTests.cs
new file mode 100644
index 0000000..d1b8598
--- /dev/null
+++ b/tests/HopFrame.Tests.Web/Components/Layout/HopFrameNavigationTests.cs
@@ -0,0 +1,68 @@
+using Bunit;
+using HopFrame.Core.Config;
+using HopFrame.Core.Services;
+using HopFrame.Web;
+using HopFrame.Web.Components.Layout;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.FluentUI.AspNetCore.Components;
+using Moq;
+
+namespace HopFrame.Tests.Web.Components.Layout;
+
+public class HopFrameNavigationTests : TestContext {
+ [Fact]
+ public void Renders_HopFrameNavigation_Components() {
+ // Arrange
+ var authHandlerMock = new Mock();
+ var config = new HopFrameConfig {
+ DisplayUserInfo = true
+ };
+
+ authHandlerMock.Setup(h => h.GetCurrentUserDisplayNameAsync())
+ .ReturnsAsync("John Doe");
+
+ Services.AddSingleton(authHandlerMock.Object);
+ Services.AddHopFrame(config);
+
+ JSInterop.Mode = JSRuntimeMode.Loose;
+
+ // Act
+ var cut = RenderComponent();
+
+ // Assert
+ var header = cut.FindComponent();
+ Assert.NotNull(header);
+
+ var persona = cut.FindComponent();
+ Assert.NotNull(persona);
+ Assert.Equal("John Doe", persona.Instance.Name);
+ Assert.Equal("JD", persona.Instance.Initials);
+ }
+
+ [Fact]
+ public void Renders_HopFrameNavigation_WithoutPersona() {
+ // Arrange
+ var authHandlerMock = new Mock();
+ var config = new HopFrameConfig {
+ DisplayUserInfo = false
+ };
+
+ authHandlerMock.Setup(h => h.GetCurrentUserDisplayNameAsync())
+ .ReturnsAsync("John Doe");
+
+ Services.AddSingleton(authHandlerMock.Object);
+ Services.AddHopFrame(config);
+
+ JSInterop.Mode = JSRuntimeMode.Loose;
+
+ // Act
+ var cut = RenderComponent();
+
+ // Assert
+ var header = cut.FindComponent();
+ Assert.NotNull(header);
+ Assert.False(cut.HasComponent());
+
+ authHandlerMock.Verify(h => h.GetCurrentUserDisplayNameAsync(), Times.Never);
+ }
+}
\ No newline at end of file
diff --git a/tests/HopFrame.Tests.Web/Components/Layout/HopFrameSideMenuTests.cs b/tests/HopFrame.Tests.Web/Components/Layout/HopFrameSideMenuTests.cs
new file mode 100644
index 0000000..6ad136e
--- /dev/null
+++ b/tests/HopFrame.Tests.Web/Components/Layout/HopFrameSideMenuTests.cs
@@ -0,0 +1,49 @@
+using HopFrame.Core.Config;
+using HopFrame.Core.Services;
+using Moq;
+using Bunit;
+using HopFrame.Tests.Web.Models;
+using HopFrame.Web;
+using HopFrame.Web.Components.Layout;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.FluentUI.AspNetCore.Components;
+
+namespace HopFrame.Tests.Web.Components.Layout;
+
+public class HopFrameSideMenuTests : TestContext {
+
+ [Fact]
+ public void Renders_FluentAppBar_Components() {
+ // Arrange
+ var contextExplorerMock = new Mock();
+ var authHandlerMock = new Mock();
+ var contextConfig = new DbContextConfig(typeof(MyDbContext));
+ var tableConfigs = new List {
+ new (contextConfig, typeof(MyTable), "Table1", 0),
+ new (contextConfig, typeof(MyTable2), "Table2", 1)
+ };
+ var config = new HopFrameConfig {
+ Contexts = { contextConfig }
+ };
+
+ contextExplorerMock.Setup(e => e.GetTables()).Returns(tableConfigs);
+ authHandlerMock.Setup(h => h.IsAuthenticatedAsync(null))
+ .ReturnsAsync(true);
+
+ Services.AddSingleton(contextExplorerMock.Object);
+ Services.AddSingleton(authHandlerMock.Object);
+ Services.AddHopFrame(config);
+
+ JSInterop.Mode = JSRuntimeMode.Loose;
+
+ // Act
+ var cut = RenderComponent();
+
+ // Assert
+ var items = cut.FindComponents();
+ Assert.Equal(tableConfigs.Count + 1, items.Count);
+ Assert.Contains(items, item => item.Instance.Text.Equals("Table1"));
+ Assert.Contains(items, item => item.Instance.Text.Equals("Table2"));
+ }
+
+}
\ No newline at end of file
diff --git a/tests/HopFrame.Tests.Web/Components/Pages/HopFrameHomeTests.cs b/tests/HopFrame.Tests.Web/Components/Pages/HopFrameHomeTests.cs
new file mode 100644
index 0000000..525c1f3
--- /dev/null
+++ b/tests/HopFrame.Tests.Web/Components/Pages/HopFrameHomeTests.cs
@@ -0,0 +1,62 @@
+using Bunit;
+using HopFrame.Core.Config;
+using HopFrame.Core.Services;
+using HopFrame.Tests.Web.Models;
+using HopFrame.Web;
+using HopFrame.Web.Components.Pages;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.FluentUI.AspNetCore.Components;
+using Moq;
+
+namespace HopFrame.Tests.Web.Components.Pages;
+
+public class HopFrameHomeTests : TestContext {
+ [Fact]
+ public void Renders_Table_Cards_Correctly() {
+ // Arrange
+ var contextExplorerMock = new Mock();
+ var authHandlerMock = new Mock();
+ var contextConfig = new DbContextConfig(typeof(MyDbContext));
+ var tableConfigs = new List {
+ new TableConfig(contextConfig, typeof(MyTable), "Table1", 0) {
+ DisplayName = "Table1",
+ ViewPolicy = "Policy1",
+ Description = "Description1"
+ },
+ new TableConfig(contextConfig, typeof(MyTable2), "Table2", 1) {
+ DisplayName = "Table2",
+ ViewPolicy = "Policy2",
+ Description = "Description2"
+ }
+ };
+ contextConfig.Tables.AddRange(tableConfigs);
+ var config = new HopFrameConfig() {
+ Contexts = { contextConfig }
+ };
+
+ contextExplorerMock.Setup(e => e.GetTables()).Returns(tableConfigs);
+ authHandlerMock.Setup(h => h.IsAuthenticatedAsync(It.IsAny()))
+ .ReturnsAsync(true);
+
+ Services.AddHopFrame(config);
+ Services.AddSingleton(contextExplorerMock.Object);
+ Services.AddSingleton(authHandlerMock.Object);
+
+ // Act
+ var cut = RenderComponent();
+
+ // Assert
+ var cards = cut.FindComponents();
+ Assert.Equal(2, cards.Count);
+
+ Assert.Contains(cards, card => card.Markup.Contains("Table1"));
+ Assert.Contains(cards, card => card.Markup.Contains("Description1"));
+ Assert.Contains(cards, card => card.Markup.Contains("Policy1"));
+ Assert.Contains(cards, card => card.Markup.Contains("Open"));
+
+ Assert.Contains(cards, card => card.Markup.Contains("Table2"));
+ Assert.Contains(cards, card => card.Markup.Contains("Description2"));
+ Assert.Contains(cards, card => card.Markup.Contains("Policy2"));
+ Assert.Contains(cards, card => card.Markup.Contains("Open"));
+ }
+}
\ No newline at end of file
diff --git a/tests/HopFrame.Tests.Web/Components/Pages/HopFrameTablePageTests.cs b/tests/HopFrame.Tests.Web/Components/Pages/HopFrameTablePageTests.cs
new file mode 100644
index 0000000..a038f86
--- /dev/null
+++ b/tests/HopFrame.Tests.Web/Components/Pages/HopFrameTablePageTests.cs
@@ -0,0 +1,96 @@
+using Bunit;
+using HopFrame.Core.Config;
+using HopFrame.Core.Services;
+using HopFrame.Tests.Web.Helpers;
+using HopFrame.Tests.Web.Models;
+using HopFrame.Web;
+using HopFrame.Web.Components.Pages;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.FluentUI.AspNetCore.Components;
+using Microsoft.JSInterop;
+using Moq;
+
+namespace HopFrame.Tests.Web.Components.Pages;
+
+public class HopFrameTablePageTests : TestContext {
+ [Fact]
+ public void Renders_Table_Correctly() {
+ // Arrange
+ var contextExplorerMock = new Mock();
+ var authHandlerMock = new Mock();
+ var dialogServiceMock = new Mock();
+ var contextConfig = new DbContextConfig(typeof(MyDbContext));
+ var managerMock = new Mock();
+ var tableConfig = new TableConfig(contextConfig, typeof(MyTable), "Table1", 0) {
+ DisplayName = "Table1",
+ ViewPolicy = "Policy1"
+ };
+ contextConfig.Tables.Add(tableConfig);
+ var config = new HopFrameConfig() {
+ Contexts = { contextConfig }
+ };
+
+ contextExplorerMock.Setup(e => e.GetTable("Table1")).Returns(tableConfig);
+ contextExplorerMock.Setup(e => e.GetTableManager("Table1")).Returns(managerMock.Object);
+ authHandlerMock.Setup(h => h.IsAuthenticatedAsync(It.IsAny())).ReturnsAsync(true);
+ managerMock.Setup(m => m.LoadPage(It.IsAny(), It.IsAny())).Returns(Enumerable.Empty