Resolve "Action Events" #66

Merged
leon.hoppe merged 1 commits from feature/events into dev 2025-02-01 11:54:07 +01:00
22 changed files with 262 additions and 68 deletions

View File

@@ -12,8 +12,28 @@
</component>
<component name="ChangeListManager">
<list default="true" id="0648788e-7696-4e60-bf12-5d5601f33d8c" name="Changes" comment="">
<change afterPath="$PROJECT_DIR$/src/HopFrame.Core/Events/EventTypes.cs" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/HopFrame.Core/Events/HopEventHandler.cs" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/HopFrame.Core/Events/IEventEmitter.cs" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/HopFrame.Core/Services/Implementations/EventEmitter.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/.idea.HopFrame/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/.idea.HopFrame/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/HopFrame.Core/Config/DbContextConfig.cs" beforeDir="false" afterPath="$PROJECT_DIR$/src/HopFrame.Core/Config/DbContextConfig.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/HopFrame.Core/Config/HopFrameConfig.cs" beforeDir="false" afterPath="$PROJECT_DIR$/src/HopFrame.Core/Config/HopFrameConfig.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/HopFrame.Core/Config/TableConfig.cs" beforeDir="false" afterPath="$PROJECT_DIR$/src/HopFrame.Core/Config/TableConfig.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/HopFrame.Core/ServiceCollectionExtensions.cs" beforeDir="false" afterPath="$PROJECT_DIR$/src/HopFrame.Core/ServiceCollectionExtensions.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/HopFrame.Web/Components/Pages/HopFrameTablePage.razor" beforeDir="false" afterPath="$PROJECT_DIR$/src/HopFrame.Web/Components/Pages/HopFrameTablePage.razor" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/HopFrame.Web/ServiceCollectionExtensions.cs" beforeDir="false" afterPath="$PROJECT_DIR$/src/HopFrame.Web/ServiceCollectionExtensions.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/testing/HopFrame.Testing/Program.cs" beforeDir="false" afterPath="$PROJECT_DIR$/testing/HopFrame.Testing/Program.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/tests/HopFrame.Tests.Core/Config/DbContextConfiguratorTests.cs" beforeDir="false" afterPath="$PROJECT_DIR$/tests/HopFrame.Tests.Core/Config/DbContextConfiguratorTests.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/tests/HopFrame.Tests.Core/Config/PropertyConfiguratorTests.cs" beforeDir="false" afterPath="$PROJECT_DIR$/tests/HopFrame.Tests.Core/Config/PropertyConfiguratorTests.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/tests/HopFrame.Tests.Core/Config/TableConfiguratorTests.cs" beforeDir="false" afterPath="$PROJECT_DIR$/tests/HopFrame.Tests.Core/Config/TableConfiguratorTests.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/tests/HopFrame.Tests.Core/Services/ContextExplorerTests.cs" beforeDir="false" afterPath="$PROJECT_DIR$/tests/HopFrame.Tests.Core/Services/ContextExplorerTests.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/tests/HopFrame.Tests.Core/Services/DisplayPropertyTests.cs" beforeDir="false" afterPath="$PROJECT_DIR$/tests/HopFrame.Tests.Core/Services/DisplayPropertyTests.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/tests/HopFrame.Tests.Core/Services/TableManagerTests.cs" beforeDir="false" afterPath="$PROJECT_DIR$/tests/HopFrame.Tests.Core/Services/TableManagerTests.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/tests/HopFrame.Tests.Web/Components/Dialogs/HopFrameEditorTests.cs" beforeDir="false" afterPath="$PROJECT_DIR$/tests/HopFrame.Tests.Web/Components/Dialogs/HopFrameEditorTests.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/tests/HopFrame.Tests.Web/Components/Layout/HopFrameSideMenuTests.cs" beforeDir="false" afterPath="$PROJECT_DIR$/tests/HopFrame.Tests.Web/Components/Layout/HopFrameSideMenuTests.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/tests/HopFrame.Tests.Web/Components/Pages/HopFrameHomeTests.cs" beforeDir="false" afterPath="$PROJECT_DIR$/tests/HopFrame.Tests.Web/Components/Pages/HopFrameHomeTests.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/tests/HopFrame.Tests.Web/Components/Pages/HopFrameTablePageTests.cs" beforeDir="false" afterPath="$PROJECT_DIR$/tests/HopFrame.Tests.Web/Components/Pages/HopFrameTablePageTests.cs" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
@@ -105,14 +125,14 @@
"keyToString": {
".NET Launch Settings Profile.HopFrame.Testing.Api: https.executor": "Run",
".NET Launch Settings Profile.HopFrame.Testing.executor": "Run",
".NET Launch Settings Profile.HopFrame.Testing: https.executor": "Run",
".NET Launch Settings Profile.HopFrame.Testing: https.executor": "Debug",
".NET Project.HopFrame.Testing.executor": "Run",
"72b118b0-a6fc-4561-acdf-74f0b454dbb8.executor": "Debug",
"RunOnceActivity.ShowReadmeOnStart": "true",
"RunOnceActivity.git.unshallow": "true",
"b5f11219-dfc4-47a1-b02c-90ab603034fb.executor": "Debug",
"dcdf1689-dc07-47e4-8824-2e60a4fbf301.executor": "Debug",
"git-widget-placeholder": "!27 on fix/selection",
"git-widget-placeholder": "!28 on feature/events",
"list.type.of.created.stylesheet": "CSS",
"node.js.detected.package.eslint": "true",
"node.js.detected.package.tslint": "true",
@@ -220,7 +240,8 @@
<workItem from="1737993570961" duration="4163000" />
<workItem from="1738054766160" duration="7449000" />
<workItem from="1738075629332" duration="8862000" />
<workItem from="1738335286481" duration="1624000" />
<workItem from="1738335286481" duration="2039000" />
<workItem from="1738403493974" duration="3350000" />
</task>
<task id="LOCAL-00001" summary="Added basic configuration">
<option name="closed" value="true" />
@@ -470,7 +491,23 @@
<option name="project" value="LOCAL" />
<updated>1738084259089</updated>
</task>
<option name="localTasksCounter" value="32" />
<task id="LOCAL-00032" summary="Removed select all button">
<option name="closed" value="true" />
<created>1738337068205</created>
<option name="number" value="00032" />
<option name="presentableId" value="LOCAL-00032" />
<option name="project" value="LOCAL" />
<updated>1738337068205</updated>
</task>
<task id="LOCAL-00033" summary="Added missing installation instructions">
<option name="closed" value="true" />
<created>1738337314351</created>
<option name="number" value="00033" />
<option name="presentableId" value="LOCAL-00033" />
<option name="project" value="LOCAL" />
<updated>1738337314351</updated>
</task>
<option name="localTasksCounter" value="34" />
<servers />
</component>
<component name="TypeScriptGeneratedFilesManager">
@@ -521,8 +558,6 @@
<component name="UnityProjectConfiguration" hasMinimizedUI="false" />
<component name="VcsManagerConfiguration">
<option name="CLEAR_INITIAL_COMMIT_MESSAGE" value="true" />
<MESSAGE value="Added relation picker dialog" />
<MESSAGE value="Added automatic relation mapping" />
<MESSAGE value="Added property validation" />
<MESSAGE value="Added creation/modification confirmation" />
<MESSAGE value="Removed Template" />
@@ -546,6 +581,27 @@
<MESSAGE value="Fixed wrong element selection for action buttons" />
<MESSAGE value="Implemented primitive change reversion" />
<MESSAGE value="Implemented deferred entry manipulation" />
<option name="LAST_COMMIT_MESSAGE" value="Implemented deferred entry manipulation" />
<MESSAGE value="Removed select all button" />
<MESSAGE value="Added missing installation instructions" />
<option name="LAST_COMMIT_MESSAGE" value="Added missing installation instructions" />
</component>
<component name="XDebuggerManager">
<breakpoint-manager>
<breakpoints>
<line-breakpoint enabled="true" type="DotNet Breakpoints">
<url>file://$PROJECT_DIR$/src/HopFrame.Core/Services/Implementations/EventEmitter.cs</url>
<line>19</line>
<properties documentPath="C:\Users\leon\Documents\Projekte\HopFrame\src\HopFrame.Core\Services\Implementations\EventEmitter.cs" containingFunctionPresentation="Method 'DispatchEvent'">
<startOffsets>
<option value="712" />
</startOffsets>
<endOffsets>
<option value="789" />
</endOffsets>
</properties>
<option name="timeStamp" value="2" />
</line-breakpoint>
</breakpoints>
</breakpoint-manager>
</component>
</project>

View File

@@ -1,13 +1,16 @@
using Microsoft.EntityFrameworkCore;
using HopFrame.Core.Events;
using Microsoft.EntityFrameworkCore;
namespace HopFrame.Core.Config;
public class DbContextConfig {
public Type ContextType { get; }
public List<TableConfig> Tables { get; } = new();
public HopFrameConfig ParentConfig { get; }
public DbContextConfig(Type context) {
public DbContextConfig(Type context, HopFrameConfig parentConfig) {
ContextType = context;
ParentConfig = parentConfig;
foreach (var property in ContextType.GetProperties()) {
if (!property.PropertyType.IsGenericType) continue;

View File

@@ -1,4 +1,5 @@
using Microsoft.EntityFrameworkCore;
using HopFrame.Core.Events;
using Microsoft.EntityFrameworkCore;
namespace HopFrame.Core.Config;
@@ -7,6 +8,7 @@ public class HopFrameConfig {
public bool DisplayUserInfo { get; set; } = true;
public string? BasePolicy { get; set; }
public string? LoginPageRewrite { get; set; }
public List<HopEventHandler> Handlers { get; } = new();
}
/// <summary>
@@ -38,7 +40,7 @@ public class HopFrameConfigurator(HopFrameConfig config) {
/// <returns>The configurator used for the DbContext</returns>
/// <seealso cref="DbContextConfigurator{TDbContext}"/>
public DbContextConfigurator<TDbContext> AddDbContext<TDbContext>() where TDbContext : DbContext {
var context = new DbContextConfig(typeof(TDbContext));
var context = new DbContextConfig(typeof(TDbContext), InnerConfig);
InnerConfig.Contexts.Add(context);
return new DbContextConfigurator<TDbContext>(context);
}

View File

@@ -2,6 +2,7 @@
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq.Expressions;
using System.Reflection;
using HopFrame.Core.Events;
namespace HopFrame.Core.Config;
@@ -188,6 +189,36 @@ public class TableConfigurator<TModel>(TableConfig config) {
InnerConfig.DeletePolicy = policy;
return this;
}
/// <summary>
/// Adds an event handler of the provided type
/// </summary>
/// <param name="type">The type of event that triggers the handler</param>
/// <param name="handler">The handler delegate</param>
public TableConfigurator<TModel> AddEventHandler(EventType type, Func<TModel, IServiceProvider, Task> handler) {
var eventName = EventTypes.ConstructEventName(type, InnerConfig);
var handlerStore = new HopEventHandler(eventName, (o, provider) => handler.Invoke((TModel)o, provider));
InnerConfig.ContextConfig.ParentConfig.Handlers.Add(handlerStore);
return this;
}
/// <summary>
/// Adds an event handler of the provided type
/// </summary>
/// <param name="type">The type of event that triggers the handler</param>
/// <param name="handler">The handler delegate</param>
public TableConfigurator<TModel> AddEventHandler(EventType type, Action<TModel, IServiceProvider> handler) {
var eventName = EventTypes.ConstructEventName(type, InnerConfig);
var handlerStore = new HopEventHandler(eventName, (o, provider) => {
handler.Invoke((TModel)o, provider);
return Task.CompletedTask;
});
InnerConfig.ContextConfig.ParentConfig.Handlers.Add(handlerStore);
return this;
}
internal static PropertyInfo GetPropertyInfo<TSource, TProperty>(Expression<Func<TSource, TProperty>> propertyLambda) {
if (propertyLambda.Body is not MemberExpression member) {

View File

@@ -0,0 +1,31 @@
using HopFrame.Core.Config;
namespace HopFrame.Core.Events;
public static class EventTypes {
private const string Prefix = "HopFrame.";
private const string CreateEntryPrefix = Prefix + "Entry.Create.";
private const string UpdateEntryPrefix = Prefix + "Entry.Update.";
private const string DeleteEntryPrefix = Prefix + "Entry.Delete.";
public static string CreateEntry(TableConfig config) => CreateEntryPrefix + config.PropertyName;
public static string UpdateEntry(TableConfig config) => UpdateEntryPrefix + config.PropertyName;
public static string DeleteEntry(TableConfig config) => DeleteEntryPrefix + config.PropertyName;
public static string ConstructEventName(EventType type, TableConfig config) {
return type switch {
EventType.CreateEntry => CreateEntry(config),
EventType.UpdateEntry => UpdateEntry(config),
EventType.DeleteEntry => DeleteEntry(config),
_ => Prefix
};
}
}
public enum EventType {
CreateEntry = 0,
UpdateEntry = 1,
DeleteEntry = 2
}

View File

@@ -0,0 +1,7 @@
namespace HopFrame.Core.Events;
public readonly struct HopEventHandler(string eventType, Func<object, IServiceProvider, Task> handler) {
public Guid Id { get; } = Guid.CreateVersion7();
public Func<object, IServiceProvider, Task> Handler { get; } = handler;
public string EventType { get; } = eventType;
}

View File

@@ -0,0 +1,14 @@
namespace HopFrame.Core.Events;
public interface IEventEmitter {
Guid RegisterEventHandler(string @event, Func<object, IServiceProvider, Task> handler);
bool RemoveEventHandler(Guid id);
Task DispatchEvent(string @event, object argument = null!);
void RemoveAllEventHandlers(string @event);
void RemoveAllEventHandlers();
}

View File

@@ -1,4 +1,5 @@
using HopFrame.Core.Services;
using HopFrame.Core.Events;
using HopFrame.Core.Services;
using HopFrame.Core.Services.Implementations;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
@@ -15,6 +16,7 @@ public static class ServiceCollectionExtensions {
public static IServiceCollection AddHopFrameServices(this IServiceCollection services) {
services.AddScoped<IContextExplorer, ContextExplorer>();
services.TryAddScoped<IHopFrameAuthHandler, DefaultAuthHandler>();
services.TryAddSingleton<IEventEmitter, EventEmitter>();
return services;
}

View File

@@ -0,0 +1,39 @@
using HopFrame.Core.Config;
using HopFrame.Core.Events;
namespace HopFrame.Core.Services.Implementations;
internal sealed class EventEmitter(IServiceProvider provider, HopFrameConfig config) : IEventEmitter {
public Guid RegisterEventHandler(string @event, Func<object, IServiceProvider, Task> handler) {
var handlerStore = new HopEventHandler(@event, handler);
config.Handlers.Add(handlerStore);
return handlerStore.Id;
}
public bool RemoveEventHandler(Guid id) {
var count = config.Handlers.RemoveAll(handler => handler.Id == id);
return count > 0;
}
public async Task DispatchEvent(string @event, object argument = null!) {
var handlers = config.Handlers.Where(handler => handler.EventType == @event);
var tasks = new List<Task>();
foreach (var handler in handlers) {
var task = handler.Handler.Invoke(argument, provider);
tasks.Add(task);
}
await Task.WhenAll(tasks);
}
public void RemoveAllEventHandlers(string @event) {
config.Handlers.RemoveAll(handler => handler.EventType == @event);
}
public void RemoveAllEventHandlers() {
config.Handlers.Clear();
}
}

View File

@@ -4,6 +4,7 @@
@implements IDisposable
@using HopFrame.Core.Config
@using HopFrame.Core.Events
@using HopFrame.Core.Services
@using HopFrame.Web.Models
@using Microsoft.JSInterop
@@ -117,6 +118,7 @@
@inject IJSRuntime Js
@inject IDialogService Dialogs
@inject IHopFrameAuthHandler Handler
@inject IEventEmitter Emitter
@code {
@@ -229,6 +231,7 @@
if (result.Cancelled) return;
await _manager!.DeleteItem(element);
await Emitter.DispatchEvent(EventTypes.DeleteEntry(_config!), element);
await Reload();
}
@@ -246,10 +249,14 @@
if (result.Cancelled) return;
if (element is null)
if (element is null) {
await _manager!.AddItem(data!.CurrentObject!);
else
await Emitter.DispatchEvent(EventTypes.CreateEntry(_config!), data.CurrentObject!);
}
else {
await _manager!.EditItem(data!.CurrentObject!);
await Emitter.DispatchEvent(EventTypes.UpdateEntry(_config!), data.CurrentObject!);
}
await Reload();
}

View File

@@ -1,5 +1,6 @@
using HopFrame.Core;
using HopFrame.Core.Config;
using HopFrame.Core.Events;
using HopFrame.Web.Components;
using HopFrame.Web.Components.Pages;
using Microsoft.Extensions.DependencyInjection;

View File

@@ -1,4 +1,5 @@
using System.Collections;
using HopFrame.Core.Events;
using HopFrame.Testing;
using Microsoft.FluentUI.AspNetCore.Components;
using HopFrame.Testing.Components;

View File

@@ -8,7 +8,7 @@ public class DbContextConfiguratorTests {
[Fact]
public void Table_WithConfigurator_InvokesConfigurator() {
// Arrange
var dbContextConfig = new DbContextConfig(typeof(MockDbContext));
var dbContextConfig = new DbContextConfig(typeof(MockDbContext), null!);
var configurator = new DbContextConfigurator<MockDbContext>(dbContextConfig);
var mockConfigurator = new Mock<Action<TableConfigurator<MockModel>>>();
@@ -22,7 +22,7 @@ public class DbContextConfiguratorTests {
[Fact]
public void Table_ReturnsCorrectTableConfigurator() {
// Arrange
var dbContextConfig = new DbContextConfig(typeof(MockDbContext));
var dbContextConfig = new DbContextConfig(typeof(MockDbContext), null!);
var configurator = new DbContextConfigurator<MockDbContext>(dbContextConfig);
// Act

View File

@@ -9,7 +9,7 @@ public class PropertyConfiguratorTests {
public void SetDisplayName_SetsNameProperty() {
// Arrange
var propertyConfig = new PropertyConfig(typeof(MockModel).GetProperty("Id")!,
new TableConfig(new DbContextConfig(typeof(MockDbContext)), typeof(MockModel), "MockModels", 0), 0);
new TableConfig(new DbContextConfig(typeof(MockDbContext), null!), typeof(MockModel), "MockModels", 0), 0);
var configurator = new PropertyConfigurator<int>(propertyConfig);
var displayName = "ID";
@@ -24,7 +24,7 @@ public class PropertyConfiguratorTests {
public void List_SetsListAndSearchableProperties() {
// Arrange
var propertyConfig = new PropertyConfig(typeof(MockModel).GetProperty("Id")!,
new TableConfig(new DbContextConfig(typeof(MockDbContext)), typeof(MockModel), "MockModels", 0), 0);
new TableConfig(new DbContextConfig(typeof(MockDbContext), null!), typeof(MockModel), "MockModels", 0), 0);
var configurator = new PropertyConfigurator<int>(propertyConfig);
// Act
@@ -39,7 +39,7 @@ public class PropertyConfiguratorTests {
public void IsSortable_SetsSortableProperty() {
// Arrange
var propertyConfig = new PropertyConfig(typeof(MockModel).GetProperty("Id")!,
new TableConfig(new DbContextConfig(typeof(MockDbContext)), typeof(MockModel), "MockModels", 0), 0);
new TableConfig(new DbContextConfig(typeof(MockDbContext), null!), typeof(MockModel), "MockModels", 0), 0);
var configurator = new PropertyConfigurator<int>(propertyConfig);
// Act
@@ -53,7 +53,7 @@ public class PropertyConfiguratorTests {
public void IsSearchable_SetsSearchableProperty() {
// Arrange
var propertyConfig = new PropertyConfig(typeof(MockModel).GetProperty("Id")!,
new TableConfig(new DbContextConfig(typeof(MockDbContext)), typeof(MockModel), "MockModels", 0), 0);
new TableConfig(new DbContextConfig(typeof(MockDbContext), null!), typeof(MockModel), "MockModels", 0), 0);
var configurator = new PropertyConfigurator<int>(propertyConfig);
// Act
@@ -67,7 +67,7 @@ public class PropertyConfiguratorTests {
public void SetDisplayedProperty_SetsDisplayedProperty() {
// Arrange
var propertyConfig = new PropertyConfig(typeof(MockModel).GetProperty("Id")!,
new TableConfig(new DbContextConfig(typeof(MockDbContext)), typeof(MockModel), "MockModels", 0), 0);
new TableConfig(new DbContextConfig(typeof(MockDbContext), null!), typeof(MockModel), "MockModels", 0), 0);
var configurator = new PropertyConfigurator<MockModel>(propertyConfig);
Expression<Func<MockModel, int>> propertyExpression = model => model.Id;
@@ -83,7 +83,7 @@ public class PropertyConfiguratorTests {
public void Format_SetsFormatter() {
// Arrange
var propertyConfig = new PropertyConfig(typeof(MockModel).GetProperty("Id")!,
new TableConfig(new DbContextConfig(typeof(MockDbContext)), typeof(MockModel), "MockModels", 0), 0);
new TableConfig(new DbContextConfig(typeof(MockDbContext), null!), typeof(MockModel), "MockModels", 0), 0);
var configurator = new PropertyConfigurator<int>(propertyConfig);
Func<int, IServiceProvider, string> formatter = (val, _) => val.ToString();
@@ -98,7 +98,7 @@ public class PropertyConfiguratorTests {
public void SetParser_SetsParser() {
// Arrange
var propertyConfig = new PropertyConfig(typeof(MockModel).GetProperty("Id")!,
new TableConfig(new DbContextConfig(typeof(MockDbContext)), typeof(MockModel), "MockModels", 0), 0);
new TableConfig(new DbContextConfig(typeof(MockDbContext), null!), typeof(MockModel), "MockModels", 0), 0);
var configurator = new PropertyConfigurator<int>(propertyConfig);
Func<string, IServiceProvider, int> parser = (str, _) => int.Parse(str);
@@ -113,7 +113,7 @@ public class PropertyConfiguratorTests {
public void SetEditable_SetsEditableProperty() {
// Arrange
var propertyConfig = new PropertyConfig(typeof(MockModel).GetProperty("Id")!,
new TableConfig(new DbContextConfig(typeof(MockDbContext)), typeof(MockModel), "MockModels", 0), 0);
new TableConfig(new DbContextConfig(typeof(MockDbContext), null!), typeof(MockModel), "MockModels", 0), 0);
var configurator = new PropertyConfigurator<int>(propertyConfig);
// Act
@@ -127,7 +127,7 @@ public class PropertyConfiguratorTests {
public void SetCreatable_SetsCreatableProperty() {
// Arrange
var propertyConfig = new PropertyConfig(typeof(MockModel).GetProperty("Id")!,
new TableConfig(new DbContextConfig(typeof(MockDbContext)), typeof(MockModel), "MockModels", 0), 0);
new TableConfig(new DbContextConfig(typeof(MockDbContext), null!), typeof(MockModel), "MockModels", 0), 0);
var configurator = new PropertyConfigurator<int>(propertyConfig);
// Act
@@ -141,7 +141,7 @@ public class PropertyConfiguratorTests {
public void DisplayValue_SetsDisplayValueProperty() {
// Arrange
var propertyConfig = new PropertyConfig(typeof(MockModel).GetProperty("Id")!,
new TableConfig(new DbContextConfig(typeof(MockDbContext)), typeof(MockModel), "MockModels", 0), 0);
new TableConfig(new DbContextConfig(typeof(MockDbContext), null!), typeof(MockModel), "MockModels", 0), 0);
var configurator = new PropertyConfigurator<int>(propertyConfig);
// Act
@@ -155,7 +155,7 @@ public class PropertyConfiguratorTests {
public void IsTextArea_SetsTextAreaProperty() {
// Arrange
var propertyConfig = new PropertyConfig(typeof(MockModel).GetProperty("Id")!,
new TableConfig(new DbContextConfig(typeof(MockDbContext)), typeof(MockModel), "MockModels", 0), 0);
new TableConfig(new DbContextConfig(typeof(MockDbContext), null!), typeof(MockModel), "MockModels", 0), 0);
var configurator = new PropertyConfigurator<int>(propertyConfig);
// Act
@@ -169,7 +169,7 @@ public class PropertyConfiguratorTests {
public void SetTextAreaRows_SetsTextAreaRowsProperty() {
// Arrange
var propertyConfig = new PropertyConfig(typeof(MockModel).GetProperty("Id")!,
new TableConfig(new DbContextConfig(typeof(MockDbContext)), typeof(MockModel), "MockModels", 0), 0);
new TableConfig(new DbContextConfig(typeof(MockDbContext), null!), typeof(MockModel), "MockModels", 0), 0);
var configurator = new PropertyConfigurator<int>(propertyConfig);
var rows = 10;
@@ -184,7 +184,7 @@ public class PropertyConfiguratorTests {
public void SetValidator_SetsValidator() {
// Arrange
var propertyConfig = new PropertyConfig(typeof(MockModel).GetProperty("Id")!,
new TableConfig(new DbContextConfig(typeof(MockDbContext)), typeof(MockModel), "MockModels", 0), 0);
new TableConfig(new DbContextConfig(typeof(MockDbContext), null!), typeof(MockModel), "MockModels", 0), 0);
var configurator = new PropertyConfigurator<int>(propertyConfig);
Func<int, IServiceProvider, IEnumerable<string>> validator = (_, _) => new List<string>();
@@ -199,7 +199,7 @@ public class PropertyConfiguratorTests {
public void SetOrderIndex_SetsOrderProperty() {
// Arrange
var propertyConfig = new PropertyConfig(typeof(MockModel).GetProperty("Id")!,
new TableConfig(new DbContextConfig(typeof(MockDbContext)), typeof(MockModel), "MockModels", 0), 0);
new TableConfig(new DbContextConfig(typeof(MockDbContext), null!), typeof(MockModel), "MockModels", 0), 0);
var configurator = new PropertyConfigurator<int>(propertyConfig);
var orderIndex = 1;
@@ -213,7 +213,7 @@ public class PropertyConfiguratorTests {
[Fact]
public void Constructor_SetsTableProperty() {
// Arrange
var tableConfig = new TableConfig(new DbContextConfig(typeof(MockDbContext)), typeof(MockModel), "MockModels", 0);
var tableConfig = new TableConfig(new DbContextConfig(typeof(MockDbContext), null!), typeof(MockModel), "MockModels", 0);
// Act
var propertyConfig = new PropertyConfig(typeof(MockModel).GetProperty("Id")!, tableConfig, 0);

View File

@@ -9,7 +9,7 @@ public class TableConfiguratorTests {
public void Ignore_SetsIgnoredProperty() {
// Arrange
var tableConfig =
new TableConfig(new DbContextConfig(typeof(MockDbContext)), typeof(MockModel), "MockModels", 0);
new TableConfig(new DbContextConfig(typeof(MockDbContext), null!), typeof(MockModel), "MockModels", 0);
var configurator = new TableConfigurator<MockModel>(tableConfig);
// Act
@@ -22,7 +22,7 @@ public class TableConfiguratorTests {
[Fact]
public void Property_ReturnsCorrectPropertyConfigurator() {
// Arrange
var tableConfig = new TableConfig(new DbContextConfig(typeof(MockDbContext)), typeof(MockModel), "MockModels", 0);
var tableConfig = new TableConfig(new DbContextConfig(typeof(MockDbContext), null!), typeof(MockModel), "MockModels", 0);
var configurator = new TableConfigurator<MockModel>(tableConfig);
Expression<Func<MockModel, int>> propertyExpression = model => model.Id;
@@ -35,7 +35,7 @@ public class TableConfiguratorTests {
public void Property_WithConfigurator_ReturnsCorrectPropertyConfigurator() {
// Arrange
var tableConfig = new TableConfig(new DbContextConfig(typeof(MockDbContext)), typeof(MockModel), "MockModels", 0);
var tableConfig = new TableConfig(new DbContextConfig(typeof(MockDbContext), null!), typeof(MockModel), "MockModels", 0);
var configurator = new TableConfigurator<MockModel>(tableConfig);
Expression<Func<MockModel, int>> propertyExpression = model => model.Id;
@@ -52,7 +52,7 @@ public class TableConfiguratorTests {
[Fact]
public void AddVirtualProperty_AddsVirtualPropertyToConfig() {
// Arrange
var tableConfig = new TableConfig(new DbContextConfig(typeof(MockDbContext)), typeof(MockModel), "MockModels", 0);
var tableConfig = new TableConfig(new DbContextConfig(typeof(MockDbContext), null!), typeof(MockModel), "MockModels", 0);
var configurator = new TableConfigurator<MockModel>(tableConfig);
Func<MockModel, IServiceProvider, string> template = (model, _) => model.Name!;
@@ -70,7 +70,7 @@ public class TableConfiguratorTests {
[Fact]
public void AddVirtualProperty_WithConfigurator_AddsVirtualPropertyToConfig() {
// Arrange
var tableConfig = new TableConfig(new DbContextConfig(typeof(MockDbContext)), typeof(MockModel), "MockModels", 0);
var tableConfig = new TableConfig(new DbContextConfig(typeof(MockDbContext), null!), typeof(MockModel), "MockModels", 0);
var configurator = new TableConfigurator<MockModel>(tableConfig);
Func<MockModel, IServiceProvider, string> template = (model, _) => model.Name!;
@@ -91,7 +91,7 @@ public class TableConfiguratorTests {
[Fact]
public void SetDisplayName_SetsDisplayNameProperty() {
// Arrange
var tableConfig = new TableConfig(new DbContextConfig(typeof(MockDbContext)), typeof(MockModel), "MockModels", 0);
var tableConfig = new TableConfig(new DbContextConfig(typeof(MockDbContext), null!), typeof(MockModel), "MockModels", 0);
var configurator = new TableConfigurator<MockModel>(tableConfig);
var displayName = "Mock Model Display Name";
@@ -105,7 +105,7 @@ public class TableConfiguratorTests {
[Fact]
public void SetDescription_SetsDescriptionProperty() {
// Arrange
var tableConfig = new TableConfig(new DbContextConfig(typeof(MockDbContext)), typeof(MockModel), "MockModels", 0);
var tableConfig = new TableConfig(new DbContextConfig(typeof(MockDbContext), null!), typeof(MockModel), "MockModels", 0);
var configurator = new TableConfigurator<MockModel>(tableConfig);
var description = "Mock Model Description";
@@ -119,7 +119,7 @@ public class TableConfiguratorTests {
[Fact]
public void SetOrderIndex_SetsOrderIndexProperty() {
// Arrange
var tableConfig = new TableConfig(new DbContextConfig(typeof(MockDbContext)), typeof(MockModel), "MockModels", 0);
var tableConfig = new TableConfig(new DbContextConfig(typeof(MockDbContext), null!), typeof(MockModel), "MockModels", 0);
var configurator = new TableConfigurator<MockModel>(tableConfig);
var orderIndex = 1;
@@ -133,7 +133,7 @@ public class TableConfiguratorTests {
[Fact]
public void SetViewPolicy_SetsViewPolicyProperty() {
// Arrange
var tableConfig = new TableConfig(new DbContextConfig(typeof(MockDbContext)), typeof(MockModel), "MockModels", 0);
var tableConfig = new TableConfig(new DbContextConfig(typeof(MockDbContext), null!), typeof(MockModel), "MockModels", 0);
var configurator = new TableConfigurator<MockModel>(tableConfig);
var policy = "ViewPolicy";
@@ -147,7 +147,7 @@ public class TableConfiguratorTests {
[Fact]
public void SetUpdatePolicy_SetsUpdatePolicyProperty() {
// Arrange
var tableConfig = new TableConfig(new DbContextConfig(typeof(MockDbContext)), typeof(MockModel), "MockModels", 0);
var tableConfig = new TableConfig(new DbContextConfig(typeof(MockDbContext), null!), typeof(MockModel), "MockModels", 0);
var configurator = new TableConfigurator<MockModel>(tableConfig);
var policy = "UpdatePolicy";
@@ -161,7 +161,7 @@ public class TableConfiguratorTests {
[Fact]
public void SetCreatePolicy_SetsCreatePolicyProperty() {
// Arrange
var tableConfig = new TableConfig(new DbContextConfig(typeof(MockDbContext)), typeof(MockModel), "MockModels", 0);
var tableConfig = new TableConfig(new DbContextConfig(typeof(MockDbContext), null!), typeof(MockModel), "MockModels", 0);
var configurator = new TableConfigurator<MockModel>(tableConfig);
var policy = "CreatePolicy";
@@ -175,7 +175,7 @@ public class TableConfiguratorTests {
[Fact]
public void SetDeletePolicy_SetsDeletePolicyProperty() {
// Arrange
var tableConfig = new TableConfig(new DbContextConfig(typeof(MockDbContext)), typeof(MockModel), "MockModels", 0);
var tableConfig = new TableConfig(new DbContextConfig(typeof(MockDbContext), null!), typeof(MockModel), "MockModels", 0);
var configurator = new TableConfigurator<MockModel>(tableConfig);
var policy = "DeletePolicy";
@@ -189,7 +189,7 @@ public class TableConfiguratorTests {
[Fact]
public void Constructor_WithKeyProperty_DisablesEdit() {
// Act
var tableConfig = new TableConfig(new DbContextConfig(typeof(MockDbContext)), typeof(MockModel2), "Models2", 0);
var tableConfig = new TableConfig(new DbContextConfig(typeof(MockDbContext), null!), typeof(MockModel2), "Models2", 0);
var prop = tableConfig.Properties.SingleOrDefault(prop => prop.Info.Name == nameof(MockModel2.Id));
// Assert
@@ -200,7 +200,7 @@ public class TableConfiguratorTests {
[Fact]
public void Constructor_WithGeneratedProperty_DisablesEditAndCreate() {
// Act
var tableConfig = new TableConfig(new DbContextConfig(typeof(MockDbContext)), typeof(MockModel2), "Models2", 0);
var tableConfig = new TableConfig(new DbContextConfig(typeof(MockDbContext), null!), typeof(MockModel2), "Models2", 0);
var prop = tableConfig.Properties.SingleOrDefault(prop => prop.Info.Name == nameof(MockModel2.Number));
// Assert

View File

@@ -11,7 +11,7 @@ public class ContextExplorerTests {
public void GetTables_ReturnsNonIgnoredTables() {
// Arrange
var config = new HopFrameConfig();
var contextConfig = new DbContextConfig(typeof(MockDbContext));
var contextConfig = new DbContextConfig(typeof(MockDbContext), null!);
var tableConfig1 = contextConfig.Tables[0];
var tableConfig2 = contextConfig.Tables[1];
config.Contexts.Add(contextConfig);
@@ -33,7 +33,7 @@ public class ContextExplorerTests {
public void GetTable_ByDisplayName_ReturnsCorrectTable() {
// Arrange
var config = new HopFrameConfig();
var contextConfig = new DbContextConfig(typeof(MockDbContext));
var contextConfig = new DbContextConfig(typeof(MockDbContext), null!);
var tableConfig = contextConfig.Tables[0];
config.Contexts.Add(contextConfig);
tableConfig.DisplayName = "TestTable";
@@ -54,7 +54,7 @@ public class ContextExplorerTests {
public void GetTable_ByDisplayName_ReturnsNullIfTableNotFound() {
// Arrange
var config = new HopFrameConfig();
var contextConfig = new DbContextConfig(typeof(MockDbContext));
var contextConfig = new DbContextConfig(typeof(MockDbContext), null!);
var tableConfig = contextConfig.Tables[0];
config.Contexts.Add(contextConfig);
tableConfig.DisplayName = "TestTable";
@@ -74,7 +74,7 @@ public class ContextExplorerTests {
public void GetTable_ByType_ReturnsCorrectTable() {
// Arrange
var config = new HopFrameConfig();
var contextConfig = new DbContextConfig(typeof(MockDbContext));
var contextConfig = new DbContextConfig(typeof(MockDbContext), null!);
var tableConfig = contextConfig.Tables[0];
config.Contexts.Add(contextConfig);
@@ -94,7 +94,7 @@ public class ContextExplorerTests {
public void GetTable_ByType_ReturnsNullIfTableNotFound() {
// Arrange
var config = new HopFrameConfig();
var contextConfig = new DbContextConfig(typeof(MockDbContext));
var contextConfig = new DbContextConfig(typeof(MockDbContext), null!);
var tableConfig = contextConfig.Tables[0];
config.Contexts.Add(contextConfig);
@@ -113,7 +113,7 @@ public class ContextExplorerTests {
public void GetTableManager_ReturnsCorrectTableManager() {
// Arrange
var config = new HopFrameConfig();
var contextConfig = new DbContextConfig(typeof(MockDbContext));
var contextConfig = new DbContextConfig(typeof(MockDbContext), null!);
var tableConfig = new TableConfig(contextConfig, typeof(MockModel), "Models", 0);
contextConfig.Tables.Add(tableConfig);
config.Contexts.Add(contextConfig);
@@ -135,7 +135,7 @@ public class ContextExplorerTests {
public void GetTableManager_ReturnsNullIfDbContextNotFound() {
// Arrange
var config = new HopFrameConfig();
var contextConfig = new DbContextConfig(typeof(MockDbContext));
var contextConfig = new DbContextConfig(typeof(MockDbContext), null!);
var tableConfig = new TableConfig(contextConfig, typeof(MockModel), "MockModels", 0);
contextConfig.Tables.Add(tableConfig);
config.Contexts.Add(contextConfig);
@@ -154,7 +154,7 @@ public class ContextExplorerTests {
public void GetTableManager_ReturnsNullIfTableNotFound() {
// Arrange
var config = new HopFrameConfig();
var contextConfig = new DbContextConfig(typeof(MockDbContext));
var contextConfig = new DbContextConfig(typeof(MockDbContext), null!);
var tableConfig = new TableConfig(contextConfig, typeof(MockModel), "Models", 0);
contextConfig.Tables.Add(tableConfig);
config.Contexts.Add(contextConfig);
@@ -175,7 +175,7 @@ public class ContextExplorerTests {
public void SeedTableData_SetsTableSeededFlag() {
// Arrange
var config = new HopFrameConfig();
var contextConfig = new DbContextConfig(typeof(MockDbContext));
var contextConfig = new DbContextConfig(typeof(MockDbContext), null!);
var tableConfig = contextConfig.Tables[0];
config.Contexts.Add(contextConfig);
@@ -194,7 +194,7 @@ public class ContextExplorerTests {
public void SeedTableData_SetsTablePropertiesCorrectly() {
// Arrange
var config = new HopFrameConfig();
var contextConfig = new DbContextConfig(typeof(MockDbContext));
var contextConfig = new DbContextConfig(typeof(MockDbContext), null!);
var tableConfig = contextConfig.Tables[0];
var tableConfig2 = contextConfig.Tables[1];
config.Contexts.Add(contextConfig);

View File

@@ -17,7 +17,7 @@ public class DisplayPropertyTests {
var contextMock = new Mock<DbContext>();
_providerMock = new Mock<IServiceProvider>();
_explorerMock = new Mock<IContextExplorer>();
_config = new TableConfig(new DbContextConfig(typeof(MockDbContext)), typeof(MockModel), "Models", 0);
_config = new TableConfig(new DbContextConfig(typeof(MockDbContext), null!), typeof(MockModel), "Models", 0);
_tableManager =
new TableManager<object>(contextMock.Object, _config, _explorerMock.Object, _providerMock.Object);
}
@@ -106,7 +106,7 @@ public class DisplayPropertyTests {
_explorerMock
.Setup(e => e.GetTable(item.Inner.GetType()))
.Returns(new TableConfig(new DbContextConfig(typeof(MockDbContext)), typeof(MockModel), "Models", 0) {
.Returns(new TableConfig(new DbContextConfig(typeof(MockDbContext), null!), typeof(MockModel), "Models", 0) {
Properties = { innerPropConfig }
});

View File

@@ -48,7 +48,7 @@ public class TableManagerTests {
new MockModel { Id = 3, Name = "Item3" }
};
var dbContext = CreateMockDbContext(data);
var config = new TableConfig(new DbContextConfig(typeof(MockDbContext)), typeof(MockModel), "Models", 0);
var config = new TableConfig(new DbContextConfig(typeof(MockDbContext), null!), typeof(MockModel), "Models", 0);
var explorer = new Mock<IContextExplorer>();
var provider = new Mock<IServiceProvider>();
var manager = new TableManager<MockModel>(dbContext.Object, config, explorer.Object, provider.Object);
@@ -70,7 +70,7 @@ public class TableManagerTests {
new MockModel { Id = 3, Name = "TestItem" }
};
var dbContext = CreateMockDbContext(data);
var config = new TableConfig(new DbContextConfig(typeof(MockDbContext)), typeof(MockModel), "Models", 0);
var config = new TableConfig(new DbContextConfig(typeof(MockDbContext), null!), typeof(MockModel), "Models", 0);
config.Properties.Add(new PropertyConfig(typeof(MockModel).GetProperty("Name")!, config, 0)
{ Searchable = true });
var explorer = new Mock<IContextExplorer>();
@@ -96,7 +96,7 @@ public class TableManagerTests {
new MockModel { Id = 3, Name = "Item3" }
};
var dbContext = new MockDbContext();
var config = new TableConfig(new DbContextConfig(typeof(MockDbContext)), typeof(MockModel), "Models", 0);
var config = new TableConfig(new DbContextConfig(typeof(MockDbContext), null!), typeof(MockModel), "Models", 0);
var explorer = new Mock<IContextExplorer>();
var provider = new Mock<IServiceProvider>();
var manager = new TableManager<MockModel>(dbContext, config, explorer.Object, provider.Object);
@@ -118,7 +118,7 @@ public class TableManagerTests {
new MockModel { Id = 2, Name = "Item2" }
};
var dbContext = CreateMockDbContext(data);
var config = new TableConfig(new DbContextConfig(typeof(MockDbContext)), typeof(MockModel), "Models", 0);
var config = new TableConfig(new DbContextConfig(typeof(MockDbContext), null!), typeof(MockModel), "Models", 0);
var explorer = new Mock<IContextExplorer>();
var provider = new Mock<IServiceProvider>();
var manager = new TableManager<MockModel>(dbContext.Object, config, explorer.Object, provider.Object);
@@ -139,7 +139,7 @@ public class TableManagerTests {
new MockModel { Id = 1, Name = "Item1" }
};
var dbContext = CreateMockDbContext(data);
var config = new TableConfig(new DbContextConfig(typeof(MockDbContext)), typeof(MockModel), "Models", 0);
var config = new TableConfig(new DbContextConfig(typeof(MockDbContext), null!), typeof(MockModel), "Models", 0);
var explorer = new Mock<IContextExplorer>();
var provider = new Mock<IServiceProvider>();
var manager = new TableManager<MockModel>(dbContext.Object, config, explorer.Object, provider.Object);
@@ -156,7 +156,7 @@ public class TableManagerTests {
// Arrange
var data = new List<MockModel>();
var dbContext = CreateMockDbContext(data);
var config = new TableConfig(new DbContextConfig(typeof(MockDbContext)), typeof(MockModel), "Models", 0);
var config = new TableConfig(new DbContextConfig(typeof(MockDbContext), null!), typeof(MockModel), "Models", 0);
var explorer = new Mock<IContextExplorer>();
var provider = new Mock<IServiceProvider>();
var manager = new TableManager<MockModel>(dbContext.Object, config, explorer.Object, provider.Object);

View File

@@ -22,7 +22,7 @@ public class HopFrameEditorTests : TestContext {
var dialogServiceMock = new Mock<IDialogService>();
var toastServiceMock = new Mock<IToastService>();
var serviceProviderMock = new Mock<IServiceProvider>();
var contextConfig = new DbContextConfig(typeof(MyDbContext));
var contextConfig = new DbContextConfig(typeof(MyDbContext), null!);
var tableConfig = new TableConfig(contextConfig, typeof(MyTable), "Table1", 0) {
DisplayName = "Table1",
ViewPolicy = "Policy1"

View File

@@ -17,7 +17,7 @@ public class HopFrameSideMenuTests : TestContext {
// Arrange
var contextExplorerMock = new Mock<IContextExplorer>();
var authHandlerMock = new Mock<IHopFrameAuthHandler>();
var contextConfig = new DbContextConfig(typeof(MyDbContext));
var contextConfig = new DbContextConfig(typeof(MyDbContext), null!);
var tableConfigs = new List<TableConfig> {
new (contextConfig, typeof(MyTable), "Table1", 0),
new (contextConfig, typeof(MyTable2), "Table2", 1)

View File

@@ -16,7 +16,7 @@ public class HopFrameHomeTests : TestContext {
// Arrange
var contextExplorerMock = new Mock<IContextExplorer>();
var authHandlerMock = new Mock<IHopFrameAuthHandler>();
var contextConfig = new DbContextConfig(typeof(MyDbContext));
var contextConfig = new DbContextConfig(typeof(MyDbContext), null!);
var tableConfigs = new List<TableConfig> {
new TableConfig(contextConfig, typeof(MyTable), "Table1", 0) {
DisplayName = "Table1",

View File

@@ -19,7 +19,7 @@ public class HopFrameTablePageTests : TestContext {
var contextExplorerMock = new Mock<IContextExplorer>();
var authHandlerMock = new Mock<IHopFrameAuthHandler>();
var dialogServiceMock = new Mock<IDialogService>();
var contextConfig = new DbContextConfig(typeof(MyDbContext));
var contextConfig = new DbContextConfig(typeof(MyDbContext), null!);
var managerMock = new Mock<ITableManager>();
var tableConfig = new TableConfig(contextConfig, typeof(MyTable), "Table1", 0) {
DisplayName = "Table1",
@@ -63,7 +63,7 @@ public class HopFrameTablePageTests : TestContext {
var contextExplorerMock = new Mock<IContextExplorer>();
var authHandlerMock = new Mock<IHopFrameAuthHandler>();
var dialogServiceMock = new Mock<IDialogService>();
var contextConfig = new DbContextConfig(typeof(MyDbContext));
var contextConfig = new DbContextConfig(typeof(MyDbContext), null!);
var tableConfig = new TableConfig(contextConfig, typeof(MyTable), "Table1", 0) {
DisplayName = "Table1",
ViewPolicy = "Policy1"