From 9a3720f05345ba95ea1239dc59a1c1365e7ae78e Mon Sep 17 00:00:00 2001 From: Loretta Date: Wed, 10 Dec 2025 09:47:06 +0100 Subject: [PATCH] Add FruitBank SANDBOX for isolated SignalR endpoint testing Introduces a new SANDBOX environment with a dedicated web app (`Mango.Sandbox.EndPoints`) for testing SignalR endpoints in isolation from the main application. Adds null plugin manager implementations to avoid plugin dependencies. Includes automated MSTest tests (`Mango.Sandbox.EndPoints.Tests`), a manual SignalR test client, and a PowerShell script for building and running the sandbox. Provides configuration files and health endpoints for robust, independent development and testing of FruitBank SignalR logic. --- FruitBank.sln | 49 +- .../Mango.Sandbox.EndPoints.Tests.csproj | 19 + .../SignalREndpointTests.cs | 218 ++++++ .../Mango.Sandbox.EndPoints.csproj | 144 ++++ .../Mango.Sandbox.EndPoints/Program.cs | 739 ++++++++++++++++++ .../NullAuthenticationPluginManager.cs | 30 + .../Services/NullDiscountPluginManager.cs | 26 + .../Services/NullExchangeRatePluginManager.cs | 31 + .../NullExternalAuthenticationService.cs | 35 + ...lMultiFactorAuthenticationPluginManager.cs | 36 + .../Services/NullPaymentPluginManager.cs | 36 + .../Services/NullPickupPluginManager.cs | 30 + .../Services/NullSearchPluginManager.cs | 33 + .../Services/NullShippingPluginManager.cs | 36 + .../Services/NullTaxPluginManager.cs | 30 + .../Services/NullWidgetPluginManager.cs | 30 + .../appsettings.Development.json | 8 + .../Mango.Sandbox.EndPoints/appsettings.json | 13 + .../Mango.Sandbox.EndPoints/test-sandbox.ps1 | 81 ++ .../Mango.Sandbox.SignalRTestClient.csproj | 11 + .../Program.cs | 48 ++ 21 files changed, 1681 insertions(+), 2 deletions(-) create mode 100644 Tests/Mango.Sandbox/Mango.Sandbox.EndPoints.Tests/Mango.Sandbox.EndPoints.Tests.csproj create mode 100644 Tests/Mango.Sandbox/Mango.Sandbox.EndPoints.Tests/SignalREndpointTests.cs create mode 100644 Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/Mango.Sandbox.EndPoints.csproj create mode 100644 Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/Program.cs create mode 100644 Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/Services/NullAuthenticationPluginManager.cs create mode 100644 Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/Services/NullDiscountPluginManager.cs create mode 100644 Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/Services/NullExchangeRatePluginManager.cs create mode 100644 Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/Services/NullExternalAuthenticationService.cs create mode 100644 Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/Services/NullMultiFactorAuthenticationPluginManager.cs create mode 100644 Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/Services/NullPaymentPluginManager.cs create mode 100644 Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/Services/NullPickupPluginManager.cs create mode 100644 Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/Services/NullSearchPluginManager.cs create mode 100644 Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/Services/NullShippingPluginManager.cs create mode 100644 Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/Services/NullTaxPluginManager.cs create mode 100644 Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/Services/NullWidgetPluginManager.cs create mode 100644 Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/appsettings.Development.json create mode 100644 Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/appsettings.json create mode 100644 Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/test-sandbox.ps1 create mode 100644 Tests/Mango.Sandbox/Mango.Sandbox.SignalRTestClient/Mango.Sandbox.SignalRTestClient.csproj create mode 100644 Tests/Mango.Sandbox/Mango.Sandbox.SignalRTestClient/Program.cs diff --git a/FruitBank.sln b/FruitBank.sln index 84afd68..4220d61 100644 --- a/FruitBank.sln +++ b/FruitBank.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.0.32002.185 +# Visual Studio Version 18 +VisualStudioVersion = 18.0.11222.15 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Libraries", "Libraries", "{E4ACA93B-D3DE-4557-B069-F1DB42925A4B}" EndProject @@ -87,6 +87,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nop.Plugin.Misc.MangoCore", EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mango.Nop.Data", "..\NopCommerce.Common\4.70\Libraries\Mango.Nop.Data\Mango.Nop.Data.csproj", "{EE44B558-F1DA-433A-BD4C-D275986A4679}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mango.Sandbox.EndPoints", "Tests\Mango.Sandbox\Mango.Sandbox.EndPoints\Mango.Sandbox.EndPoints.csproj", "{D22DB269-2490-4A3D-B0B4-2CD2BB626F9C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mango.Sandbox.EndPoints.Tests", "Tests\Mango.Sandbox\Mango.Sandbox.EndPoints.Tests\Mango.Sandbox.EndPoints.Tests.csproj", "{B8491E5C-DBB5-1594-052E-744D78D7A4DE}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mango.Sandbox.SignalRTestClient", "Tests\Mango.Sandbox\Mango.Sandbox.SignalRTestClient\Mango.Sandbox.SignalRTestClient.csproj", "{B2FBDB33-24F4-E0B1-0EA7-7939A387F88F}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -507,6 +513,42 @@ Global {EE44B558-F1DA-433A-BD4C-D275986A4679}.Release|Mixed Platforms.Build.0 = Release|Any CPU {EE44B558-F1DA-433A-BD4C-D275986A4679}.Release|x86.ActiveCfg = Release|Any CPU {EE44B558-F1DA-433A-BD4C-D275986A4679}.Release|x86.Build.0 = Release|Any CPU + {D22DB269-2490-4A3D-B0B4-2CD2BB626F9C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D22DB269-2490-4A3D-B0B4-2CD2BB626F9C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D22DB269-2490-4A3D-B0B4-2CD2BB626F9C}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {D22DB269-2490-4A3D-B0B4-2CD2BB626F9C}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {D22DB269-2490-4A3D-B0B4-2CD2BB626F9C}.Debug|x86.ActiveCfg = Debug|Any CPU + {D22DB269-2490-4A3D-B0B4-2CD2BB626F9C}.Debug|x86.Build.0 = Debug|Any CPU + {D22DB269-2490-4A3D-B0B4-2CD2BB626F9C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D22DB269-2490-4A3D-B0B4-2CD2BB626F9C}.Release|Any CPU.Build.0 = Release|Any CPU + {D22DB269-2490-4A3D-B0B4-2CD2BB626F9C}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {D22DB269-2490-4A3D-B0B4-2CD2BB626F9C}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {D22DB269-2490-4A3D-B0B4-2CD2BB626F9C}.Release|x86.ActiveCfg = Release|Any CPU + {D22DB269-2490-4A3D-B0B4-2CD2BB626F9C}.Release|x86.Build.0 = Release|Any CPU + {B8491E5C-DBB5-1594-052E-744D78D7A4DE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B8491E5C-DBB5-1594-052E-744D78D7A4DE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B8491E5C-DBB5-1594-052E-744D78D7A4DE}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {B8491E5C-DBB5-1594-052E-744D78D7A4DE}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {B8491E5C-DBB5-1594-052E-744D78D7A4DE}.Debug|x86.ActiveCfg = Debug|Any CPU + {B8491E5C-DBB5-1594-052E-744D78D7A4DE}.Debug|x86.Build.0 = Debug|Any CPU + {B8491E5C-DBB5-1594-052E-744D78D7A4DE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B8491E5C-DBB5-1594-052E-744D78D7A4DE}.Release|Any CPU.Build.0 = Release|Any CPU + {B8491E5C-DBB5-1594-052E-744D78D7A4DE}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {B8491E5C-DBB5-1594-052E-744D78D7A4DE}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {B8491E5C-DBB5-1594-052E-744D78D7A4DE}.Release|x86.ActiveCfg = Release|Any CPU + {B8491E5C-DBB5-1594-052E-744D78D7A4DE}.Release|x86.Build.0 = Release|Any CPU + {B2FBDB33-24F4-E0B1-0EA7-7939A387F88F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B2FBDB33-24F4-E0B1-0EA7-7939A387F88F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B2FBDB33-24F4-E0B1-0EA7-7939A387F88F}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {B2FBDB33-24F4-E0B1-0EA7-7939A387F88F}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {B2FBDB33-24F4-E0B1-0EA7-7939A387F88F}.Debug|x86.ActiveCfg = Debug|Any CPU + {B2FBDB33-24F4-E0B1-0EA7-7939A387F88F}.Debug|x86.Build.0 = Debug|Any CPU + {B2FBDB33-24F4-E0B1-0EA7-7939A387F88F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B2FBDB33-24F4-E0B1-0EA7-7939A387F88F}.Release|Any CPU.Build.0 = Release|Any CPU + {B2FBDB33-24F4-E0B1-0EA7-7939A387F88F}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {B2FBDB33-24F4-E0B1-0EA7-7939A387F88F}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {B2FBDB33-24F4-E0B1-0EA7-7939A387F88F}.Release|x86.ActiveCfg = Release|Any CPU + {B2FBDB33-24F4-E0B1-0EA7-7939A387F88F}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -550,6 +592,9 @@ Global {3E893AC2-29F1-48FC-B33F-F73C6EE2BE90} = {0742FDF3-0F2E-4C64-9521-E58A7FF2ED26} {3976CB1D-8080-4B84-8C01-1F98BFCAF2B3} = {0742FDF3-0F2E-4C64-9521-E58A7FF2ED26} {EE44B558-F1DA-433A-BD4C-D275986A4679} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8} + {D22DB269-2490-4A3D-B0B4-2CD2BB626F9C} = {E8FC6874-E230-468A-9685-4747354B92FF} + {B8491E5C-DBB5-1594-052E-744D78D7A4DE} = {E8FC6874-E230-468A-9685-4747354B92FF} + {B2FBDB33-24F4-E0B1-0EA7-7939A387F88F} = {E8FC6874-E230-468A-9685-4747354B92FF} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {EE72A8B2-332A-4175-9319-6726D36E9D25} diff --git a/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints.Tests/Mango.Sandbox.EndPoints.Tests.csproj b/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints.Tests/Mango.Sandbox.EndPoints.Tests.csproj new file mode 100644 index 0000000..0c2b8e2 --- /dev/null +++ b/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints.Tests/Mango.Sandbox.EndPoints.Tests.csproj @@ -0,0 +1,19 @@ + + + + net9.0 + enable + enable + false + true + + + + + + + + + + + diff --git a/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints.Tests/SignalREndpointTests.cs b/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints.Tests/SignalREndpointTests.cs new file mode 100644 index 0000000..76a7aa6 --- /dev/null +++ b/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints.Tests/SignalREndpointTests.cs @@ -0,0 +1,218 @@ +using Microsoft.AspNetCore.SignalR.Client; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System.Diagnostics; +using System.Text; +using System.Text.Json; + +namespace Mango.Sandbox.EndPoints.Tests; + +/// +/// SignalR Endpoint tesztek. +/// FONTOS: A SANDBOX-ot manuálisan kell elindítani a tesztek futtatása előtt! +// Indítás: dotnet run --project Mango.Sandbox.EndPoints --urls http://localhost:59579 +/// +[TestClass] +public class SignalREndpointTests +{ + private static readonly string SandboxUrl = "http://localhost:59579"; + private static readonly string HubUrl = $"{SandboxUrl}/fbHub"; + + // SignalR Tags from FruitBank.Common.SignalRs.SignalRTags + private const int GetMeasuringUsersTag = 70; + private const int GetStockQuantityHistoryDtosTag = 40; + private const int GetStockQuantityHistoryDtosByProductIdTag = 41; + private const int GetShippingDocumentsByShippingIdTag = 60; + private const int GetOrderDtoByIdTag = 21; + private const int GetStockTakingItemsByIdTag = 81; + + [ClassInitialize] + public static async Task ClassInitialize(TestContext context) + { + using var httpClient = new HttpClient { Timeout = TimeSpan.FromSeconds(5) }; + try + { + var response = await httpClient.GetAsync($"{SandboxUrl}/health"); + Assert.IsTrue(response.IsSuccessStatusCode, + "SANDBOX is not running! Start it manually: dotnet run --project Mango.Sandbox.EndPoints --urls http://localhost:59579"); + } + catch (Exception ex) + { + Assert.Fail($"SANDBOX is not running! Error: {ex.Message}\n" + + "Start it manually: dotnet run --project Mango.Sandbox.EndPoints --urls http://localhost:59579"); + } + } + + #region HTTP Endpoint Tests + + [TestMethod] + public async Task HealthEndpoint_ReturnsSuccess() + { + using var httpClient = new HttpClient(); + var response = await httpClient.GetAsync($"{SandboxUrl}/health"); + Assert.IsTrue(response.IsSuccessStatusCode, $"Health endpoint returned {response.StatusCode}"); + } + + [TestMethod] + public async Task RootEndpoint_ReturnsSandboxIsRunning() + { + using var httpClient = new HttpClient(); + var response = await httpClient.GetStringAsync(SandboxUrl); + Assert.AreEqual("SANDBOX is running!", response); + } + + #endregion + + #region SignalR Connection Tests + + [TestMethod] + public async Task SignalR_Negotiate_ReturnsSuccess() + { + using var httpClient = new HttpClient(); + var response = await httpClient.PostAsync($"{HubUrl}/negotiate?negotiateVersion=1", null); + Assert.IsTrue(response.IsSuccessStatusCode, $"SignalR negotiate returned {response.StatusCode}"); + } + + [TestMethod] + public async Task SignalR_Connect_Succeeds() + { + var connection = new HubConnectionBuilder() + .WithUrl(HubUrl) + .Build(); + + try + { + await connection.StartAsync(); + Assert.AreEqual(HubConnectionState.Connected, connection.State); + } + finally + { + await connection.StopAsync(); + } + } + + #endregion + + #region SignalR Business Endpoint Tests + + [TestMethod] + public async Task SignalR_GetMeasuringUsers_ReturnsJson() + { + await TestSignalREndpoint(GetMeasuringUsersTag, null, "GetMeasuringUsers"); + } + + [TestMethod] + public async Task SignalR_GetStockQuantityHistoryDtos_ReturnsJson() + { + await TestSignalREndpoint(GetStockQuantityHistoryDtosTag, null, "GetStockQuantityHistoryDtos"); + } + + [TestMethod] + public async Task SignalR_GetStockQuantityHistoryDtosByProductId_ReturnsJson() + { + // ProductId = 10 + await TestSignalREndpoint(GetStockQuantityHistoryDtosByProductIdTag, 10, "GetStockQuantityHistoryDtosByProductId"); + } + + [TestMethod] + public async Task SignalR_GetShippingDocumentsByShippingId_ReturnsJson() + { + // ShippingId = 5 + await TestSignalREndpoint(GetShippingDocumentsByShippingIdTag, 5, "GetShippingDocumentsByShippingId"); + } + + [TestMethod] + public async Task SignalR_GetOrderDtoById_ReturnsJson() + { + // OrderId = 15 + await TestSignalREndpoint(GetOrderDtoByIdTag, 15, "GetOrderDtoById"); + } + + [TestMethod] + public async Task SignalR_GetStockTakingItemsById_ReturnsJson() + { + // StockTakingItemId = 200 + await TestSignalREndpoint(GetStockTakingItemsByIdTag, 200, "GetStockTakingItemsById"); + } + + #endregion + + #region Helper Methods + + private async Task TestSignalREndpoint(int tag, object? parameter, string endpointName) + { + var connection = new HubConnectionBuilder() + .WithUrl(HubUrl) + .Build(); + + string? receivedJson = null; + int receivedTag = -1; + var responseReceived = new TaskCompletionSource(); + + connection.On("ReceiveMessage", (responseTag, data) => + { + receivedTag = responseTag; + if (data != null && data.Length > 0) + { + receivedJson = Encoding.UTF8.GetString(data); + } + responseReceived.TrySetResult(true); + }); + + try + { + await connection.StartAsync(); + Assert.AreEqual(HubConnectionState.Connected, connection.State, $"Failed to connect to SignalR hub for {endpointName}"); + + // Készítsük el a request data-t + byte[] requestData = parameter != null + ? Encoding.UTF8.GetBytes(JsonSerializer.Serialize(parameter)) + : Array.Empty(); + + await connection.InvokeAsync("ReceiveMessage", tag, requestData); + + var completed = await Task.WhenAny(responseReceived.Task, Task.Delay(15000)); + + if (completed == responseReceived.Task) + { + Console.WriteLine($"[{endpointName}] Response tag: {receivedTag}"); + Console.WriteLine($"[{endpointName}] Response JSON: {receivedJson?.Substring(0, Math.Min(500, receivedJson?.Length ?? 0))}..."); + + // Ellenőrizzük, hogy valid JSON-e (ha van adat) + if (!string.IsNullOrEmpty(receivedJson)) + { + try + { + var jsonDoc = JsonDocument.Parse(receivedJson); + Assert.IsTrue( + jsonDoc.RootElement.ValueKind == JsonValueKind.Array || + jsonDoc.RootElement.ValueKind == JsonValueKind.Object || + jsonDoc.RootElement.ValueKind == JsonValueKind.Null, + $"[{endpointName}] Response is not a valid JSON"); + } + catch (JsonException ex) + { + Assert.Fail($"[{endpointName}] Invalid JSON response: {ex.Message}"); + } + } + } + else + { + Assert.AreEqual(HubConnectionState.Connected, connection.State, + $"[{endpointName}] Connection was closed - check SANDBOX logs for DI errors"); + } + } + catch (Exception ex) + { + Assert.Fail($"[{endpointName}] SignalR error: {ex.Message}. Check SANDBOX logs for missing DI registrations."); + } + finally + { + if (connection.State == HubConnectionState.Connected) + { + await connection.StopAsync(); + } + } + } + + #endregion +} diff --git a/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/Mango.Sandbox.EndPoints.csproj b/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/Mango.Sandbox.EndPoints.csproj new file mode 100644 index 0000000..7337993 --- /dev/null +++ b/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/Mango.Sandbox.EndPoints.csproj @@ -0,0 +1,144 @@ + + + + net9.0 + enable + enable + + false + + $([System.IO.Path]::GetFullPath('$(MSBuildProjectDirectory)\..\..\..'))\ + $([System.IO.Path]::GetFullPath('$(MSBuildProjectDirectory)\..\..\..\..'))\ + $(FruitBankRoot)Presentation\Nop.Web\Plugins\Misc.FruitBankPlugin\ + $(SourceRoot)FruitBankHybridApp\ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $(PluginOutputDir)Nop.Plugin.Misc.FruitBankPlugin.dll + + + $(PluginOutputDir)Mango.Nop.Core.dll + + + $(PluginOutputDir)Mango.Nop.Services.dll + + + + + + + $(FruitBankHybridRoot)FruitBank.Common.Server\bin\Debug\net9.0\AyCode.Core.dll + + + $(FruitBankHybridRoot)FruitBank.Common.Server\bin\Debug\net9.0\AyCode.Core.Server.dll + + + $(FruitBankHybridRoot)FruitBank.Common.Server\bin\Debug\net9.0\AyCode.Database.dll + + + $(FruitBankHybridRoot)FruitBank.Common.Server\bin\Debug\net9.0\AyCode.Entities.dll + + + $(FruitBankHybridRoot)FruitBank.Common.Server\bin\Debug\net9.0\AyCode.Entities.Server.dll + + + $(FruitBankHybridRoot)FruitBank.Common.Server\bin\Debug\net9.0\AyCode.Interfaces.dll + + + $(FruitBankHybridRoot)FruitBank.Common.Server\bin\Debug\net9.0\AyCode.Interfaces.Server.dll + + + $(FruitBankHybridRoot)FruitBank.Common.Server\bin\Debug\net9.0\AyCode.Models.Server.dll + + + $(FruitBankHybridRoot)FruitBank.Common.Server\bin\Debug\net9.0\AyCode.Services.dll + + + $(FruitBankHybridRoot)FruitBank.Common.Server\bin\Debug\net9.0\AyCode.Services.Server.dll + + + $(FruitBankHybridRoot)FruitBank.Common.Server\bin\Debug\net9.0\AyCode.Utils.dll + + + $(FruitBankHybridRoot)FruitBank.Common.Server\bin\Debug\net9.0\FruitBank.Common.dll + + + $(FruitBankHybridRoot)FruitBank.Common.Server\bin\Debug\net9.0\FruitBank.Common.Server.dll + + + + diff --git a/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/Program.cs b/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/Program.cs new file mode 100644 index 0000000..c674ff9 --- /dev/null +++ b/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/Program.cs @@ -0,0 +1,739 @@ +using AyCode.Core.Loggers; +using FluentValidation; +using FluentValidation.AspNetCore; +using FruitBank.Common; +using FruitBank.Common.Interfaces; +using FruitBank.Common.Server.Interfaces; +using FruitBank.Common.Server.Services.Loggers; +using FruitBank.Common.Server.Services.SignalRs; +using Mango.Nop.Services; +using Mango.Nop.Services.Loggers; +using Mango.Sandbox.EndPoints.Services; +using Microsoft.AspNetCore.Http.Connections; +using Microsoft.AspNetCore.Mvc.Infrastructure; +using Nop.Core; +using Nop.Core.Caching; +using Nop.Core.Configuration; +using Nop.Core.Domain; +using Nop.Core.Domain.Blogs; +using Nop.Core.Domain.Catalog; +using Nop.Core.Domain.Common; +using Nop.Core.Domain.Customers; +using Nop.Core.Domain.Directory; +using Nop.Core.Domain.Forums; +using Nop.Core.Domain.Gdpr; +using Nop.Core.Domain.Localization; +using Nop.Core.Domain.Media; +using Nop.Core.Domain.Messages; +using Nop.Core.Domain.News; +using Nop.Core.Domain.Orders; +using Nop.Core.Domain.Payments; +using Nop.Core.Domain.Security; +using Nop.Core.Domain.Seo; +using Nop.Core.Domain.Shipping; +using Nop.Core.Domain.Stores; +using Nop.Core.Domain.Tax; +using Nop.Core.Domain.Vendors; +using Nop.Core.Events; +using Nop.Core.Http; +using Nop.Core.Infrastructure; +using Nop.Core.Security; +using Nop.Data; +using Nop.Data.DataProviders; +using Nop.Data.Mapping; +using Nop.Plugin.Misc.FruitBankPlugin.Areas.Admin.Controllers; +using Nop.Plugin.Misc.FruitBankPlugin.Controllers; +using Nop.Plugin.Misc.FruitBankPlugin.Domains.DataLayer; +using Nop.Plugin.Misc.FruitBankPlugin.Factories; +using Nop.Plugin.Misc.FruitBankPlugin.Mapping; +using Nop.Plugin.Misc.FruitBankPlugin.Services; +using Nop.Services.Affiliates; +using Nop.Services.Attributes; +using Nop.Services.Authentication; +using Nop.Services.Authentication.External; +using Nop.Services.Authentication.MultiFactor; +using Nop.Services.Blogs; +using Nop.Services.Caching; +using Nop.Services.Catalog; +using Nop.Services.Cms; +using Nop.Services.Common; +using Nop.Services.Configuration; +using Nop.Services.Customers; +using Nop.Services.Directory; +using Nop.Services.Discounts; +using Nop.Services.Events; +using Nop.Services.ExportImport; +using Nop.Services.Forums; +using Nop.Services.Gdpr; +using Nop.Services.Helpers; +using Nop.Services.Html; +using Nop.Services.Installation; +using Nop.Services.Localization; +using Nop.Services.Logging; +using Nop.Services.Media; +using Nop.Services.Media.RoxyFileman; +using Nop.Services.Messages; +using Nop.Services.News; +using Nop.Services.Orders; +using Nop.Services.Payments; +using Nop.Services.Plugins; +using Nop.Services.Plugins.Marketplace; +using Nop.Services.Polls; +using Nop.Services.ScheduleTasks; +using Nop.Services.Security; +using Nop.Services.Seo; +using Nop.Services.Shipping; +using Nop.Services.Shipping.Date; +using Nop.Services.Shipping.Pickup; +using Nop.Services.Stores; +using Nop.Services.Tax; +using Nop.Services.Themes; +using Nop.Services.Topics; +using Nop.Services.Vendors; +using Nop.Web.Areas.Admin.Factories; +using Nop.Web.Areas.Admin.Helpers; +using Nop.Web.Framework; +using Nop.Web.Framework.Factories; +using Nop.Web.Framework.Infrastructure; +using Nop.Web.Framework.Menu; +using Nop.Web.Framework.Mvc.Routing; +using Nop.Web.Framework.Themes; +using Nop.Web.Framework.UI; +using Nop.Web.Infrastructure.Installation; +using System.Net.Http.Headers; + +var builder = WebApplication.CreateBuilder(args); + +// =========================================== +// === KONFIGURÁCIÓ === +// =========================================== + +var prodAppSettingsPath = Path.GetFullPath(Path.Combine( + builder.Environment.ContentRootPath, + "..", "..", "..", + "Presentation", "Nop.Web", "App_Data", "appsettings.json")); + +if (File.Exists(prodAppSettingsPath)) +{ + builder.Configuration.AddJsonFile(prodAppSettingsPath, optional: false, reloadOnChange: true); + Console.WriteLine($"[SANDBOX] PROD config loaded: {prodAppSettingsPath}"); +} +else +{ + Console.WriteLine($"[SANDBOX] WARNING: PROD appsettings.json not found at: {prodAppSettingsPath}"); +} + +builder.Configuration.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true); +Console.WriteLine("[SANDBOX] SANDBOX config overrides applied"); + +// =========================================== +// === NAME COMPATIBILITY - LinqToDB tábla mapping === +// =========================================== + +NameCompatibilityManager.AdditionalNameCompatibilities.Add(typeof(NameCompatibility)); +Console.WriteLine("[SANDBOX] FruitBank NameCompatibility registered for LinqToDB table mapping"); + +// =========================================== +// === FILE PROVIDER (STATIC) === +// =========================================== + +CommonHelper.DefaultFileProvider = new NopFileProvider(builder.Environment); + +// =========================================== +// === TYPE FINDER === +// =========================================== + +var typeFinder = new WebAppTypeFinder(); +Singleton.Instance = typeFinder; +builder.Services.AddSingleton(typeFinder); +Console.WriteLine("[SANDBOX] TypeFinder registered"); + +// =========================================== +// === ENGINE === +// =========================================== + +var engine = new NopEngine(); +Singleton.Instance = engine; +builder.Services.AddSingleton(engine); +Console.WriteLine("[SANDBOX] NopEngine registered"); + +// =========================================== +// === CORS === +// =========================================== + +builder.Services.AddCors(options => +{ + options.AddDefaultPolicy(policy => + { + policy.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader(); + }); + + options.AddPolicy("SignalR", policy => + { + policy.SetIsOriginAllowed(_ => true).AllowAnyMethod().AllowAnyHeader().AllowCredentials(); + }); +}); + +// =========================================== +// === DI VALIDÁCIÓ KIKAPCSOLÁSA === +// =========================================== + +builder.Host.UseDefaultServiceProvider(options => +{ + options.ValidateScopes = false; + options.ValidateOnBuild = false; +}); + +// =========================================== +// === MVC INFRASTRUKTÚRA === +// =========================================== + +builder.Services.AddControllersWithViews(); +builder.Services.AddRazorPages(); +builder.Services.AddSession(); + +// =========================================== +// === ALAPVETŐ INFRASTRUKTÚRA === +// =========================================== + +builder.Services.AddHttpContextAccessor(); +builder.Services.AddSingleton(); +builder.Services.AddMemoryCache(); + +// =========================================== +// === APP SETTINGS === +// =========================================== + +var appSettings = new AppSettings(); +builder.Configuration.Bind(appSettings); +builder.Services.AddSingleton(appSettings); +Singleton.Instance = appSettings; + +// =========================================== +// === FILE PROVIDER (DI) === +// =========================================== + +builder.Services.AddScoped(); + +// =========================================== +// === ADATBÁZIS ÉS REPOSITORY === +// =========================================== + +builder.Services.AddScoped(); +builder.Services.AddScoped(typeof(IRepository<>), typeof(EntityRepository<>)); + +// =========================================== +// === CACHE SZOLGÁLTATÁSOK === +// =========================================== + +builder.Services.AddTransient(typeof(IConcurrentCollection<>), typeof(ConcurrentTrie<>)); +builder.Services.AddSingleton(); +builder.Services.AddScoped(); +builder.Services.AddSingleton(); +builder.Services.AddSingleton(); +builder.Services.AddScoped(); + +// =========================================== +// === EVENT PUBLISHER === +// =========================================== + +builder.Services.AddSingleton(); + +// =========================================== +// === LAZY WRAPPERS === +// =========================================== + +builder.Services.AddScoped(typeof(Lazy<>), typeof(LazyInstance<>)); + +// =========================================== +// === NOP SETTINGS (Domain Settings) - DINAMIKUS REGISZTRÁCIÓ === +// =========================================== + +// Alapvető Settings-ek fix értékekkel (amik a SANDBOX működéséhez szükségesek) +builder.Services.AddScoped(sp => new CookieSettings()); +builder.Services.AddScoped(sp => new CurrencySettings { PrimaryStoreCurrencyId = 1 }); +builder.Services.AddScoped(sp => new LocalizationSettings { DefaultAdminLanguageId = 1, AutomaticallyDetectLanguage = false }); +builder.Services.AddScoped(sp => new TaxSettings { TaxDisplayType = TaxDisplayType.IncludingTax }); +builder.Services.AddScoped(sp => new CatalogSettings()); +builder.Services.AddScoped(sp => new OrderSettings()); +builder.Services.AddScoped(sp => new ShippingSettings()); +builder.Services.AddScoped(sp => new RewardPointsSettings()); +builder.Services.AddScoped(sp => new CustomerSettings()); +builder.Services.AddScoped(sp => new CommonSettings()); +builder.Services.AddScoped(sp => new ShoppingCartSettings()); +builder.Services.AddScoped(sp => new MediaSettings()); +builder.Services.AddScoped(sp => new StoreInformationSettings()); +builder.Services.AddScoped(sp => new SeoSettings()); +builder.Services.AddScoped(sp => new SecuritySettings()); +builder.Services.AddScoped(sp => new AdminAreaSettings()); +builder.Services.AddScoped(sp => new EmailAccountSettings()); +builder.Services.AddScoped(sp => new MessagesSettings()); +builder.Services.AddScoped(sp => new ExternalAuthenticationSettings()); +builder.Services.AddScoped(sp => new VendorSettings()); +builder.Services.AddScoped(sp => new BlogSettings()); +builder.Services.AddScoped(sp => new NewsSettings()); +builder.Services.AddScoped(sp => new ForumSettings()); +builder.Services.AddScoped(sp => new GdprSettings()); +builder.Services.AddScoped(sp => new PaymentSettings()); +builder.Services.AddScoped(sp => new AddressSettings()); +builder.Services.AddScoped(sp => new DateTimeSettings()); +builder.Services.AddScoped(sp => new CaptchaSettings()); +builder.Services.AddScoped(sp => new DisplayDefaultMenuItemSettings()); +builder.Services.AddScoped(sp => new DisplayDefaultFooterItemSettings()); +builder.Services.AddScoped(sp => new PdfSettings()); +builder.Services.AddScoped(sp => new RobotsTxtSettings()); +builder.Services.AddScoped(sp => new SitemapSettings()); +builder.Services.AddScoped(sp => new SitemapXmlSettings()); +builder.Services.AddScoped(sp => new MeasureSettings()); +builder.Services.AddScoped(sp => new MultiFactorAuthenticationSettings()); +builder.Services.AddScoped(sp => new ProxySettings()); + +// További Settings-ek (Nop.Core.Domain namespace-ekből) +builder.Services.AddScoped(sp => new Nop.Core.Domain.Catalog.ProductEditorSettings()); +builder.Services.AddScoped(sp => new Nop.Core.Domain.Messages.MessageTemplatesSettings()); + +// =========================================== +// === NOP CORE SZOLGÁLTATÁSOK === +// =========================================== + +// Web & Utils +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); + +// Context +builder.Services.AddScoped(); +builder.Services.AddScoped(); + +// Plugins +builder.Services.AddScoped(); +builder.Services.AddScoped(); + +// Settings & Config +builder.Services.AddScoped(); + +// Security & Permission +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); + +// Authentication +builder.Services.AddScoped(); +builder.Services.AddScoped(); + +// Store +builder.Services.AddScoped(); +builder.Services.AddScoped(); + +// Localization +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); + +// Currency & Directory +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); + +// Customer +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); + +// Address & Vendor & Affiliate +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); + +// Generic Attribute +builder.Services.AddScoped(); + +// Maintenance +builder.Services.AddScoped(); + +// Catalog +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); + +// Pricing (CustomPriceCalculationService a FruitBank-ból) +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); + +// Search +builder.Services.AddScoped(); + +// Orders +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); + +// Shipping +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); + +// Tax +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); + +// Payment +builder.Services.AddScoped(); + +// Discounts +builder.Services.AddScoped(); + +// Media +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); + +// Messages & Notifications +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); + +// SEO & HTML +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); + +// Logging +builder.Services.AddScoped(); + +// Topics & Content +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); + +// GDPR +builder.Services.AddScoped(); + +// Export/Import +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); + +// Themes +builder.Services.AddScoped(); +builder.Services.AddScoped(); + +// Schedule Tasks +builder.Services.AddSingleton(); +builder.Services.AddTransient(); +builder.Services.AddScoped(); + +// Installation +builder.Services.AddScoped(); +builder.Services.AddScoped(); + +// Slug Route Transformer (ha van adatbázis) +builder.Services.AddScoped(); + +// Routing +builder.Services.AddSingleton(); + +// Roxy File Manager +builder.Services.AddScoped(); +builder.Services.AddScoped(); + +// Web Framework +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); + +// Attribute Services (generic) +builder.Services.AddScoped(typeof(IAttributeService<,>), typeof(AttributeService<,>)); +builder.Services.AddScoped(typeof(IAttributeParser<,>), typeof(Nop.Services.Attributes.AttributeParser<,>)); +builder.Services.AddScoped(typeof(IAttributeFormatter<,>), typeof(AttributeFormatter<,>)); + +// Plugin Managers (generic) +builder.Services.AddScoped(typeof(IPluginManager<>), typeof(PluginManager<>)); + +// =========================================== +// === PLUGIN MANAGEREK (Null implementációk) === +// =========================================== + +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); + +// =========================================== +// === NOP.WEB COMMON FACTORIES (Nop.Web\Infrastructure\NopStartup.cs) === +// =========================================== + +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); + +// =========================================== +// === NOP.WEB ADMIN MODEL FACTORIES (Nop.Web\Infrastructure\NopStartup.cs) === +// =========================================== + +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +// IOrderModelFactory - FruitBank CustomOrderModelFactory felülírja! +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +// IProductModelFactory - FruitBank CustomProductModelFactory felülírja! +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); + +// =========================================== +// === NOP.WEB PUBLIC FACTORIES (Nop.Web\Infrastructure\NopStartup.cs) === +// =========================================== + +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); + +// =========================================== +// === NOP.WEB HELPERS === +// =========================================== + +builder.Services.AddScoped(); + +// =========================================== +// === FRUITBANK PLUGIN SZOLGÁLTATÁSOK (PluginNopStartup-ból) === +// ===========================================; + +// Logger +builder.Services.AddScoped(); +builder.Services.AddTransient(); +builder.Services.AddScoped(); +builder.Services.AddSingleton(); + +// Core +builder.Services.AddSingleton(); +builder.Services.AddScoped(); + +// Event Consumer +builder.Services.AddScoped, EventConsumer>(); + +// Business Services +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); + +// ReplicateService with HttpClient +builder.Services.AddScoped(); +builder.Services.AddHttpClient(client => +{ + client.DefaultRequestHeaders.Authorization = + new AuthenticationHeaderValue("Bearer", "r8_MUApXYIE5mRjxqy20tsGLehWBJkCzNj0Cwvrh"); +}); + +// DbTable Services +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); + +// DbContext Services +builder.Services.AddScoped(); +builder.Services.AddScoped(); + +// SignalR Services +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); + +// =========================================== +// === SIGNALR KONFIGURÁCIÓ === +// =========================================== + +builder.Services.AddSignalR(hubOptions => +{ + hubOptions.EnableDetailedErrors = true; + hubOptions.MaximumReceiveMessageSize = 30_000_000; + hubOptions.KeepAliveInterval = TimeSpan.FromSeconds(FruitBankConstClient.SignalRKeepAliveIntervalSecond); + hubOptions.ClientTimeoutInterval = TimeSpan.FromSeconds(FruitBankConstClient.SignarlRTimeoutIntervalSecond); + hubOptions.StatefulReconnectBufferSize = 30_000_000; +}); + +// =========================================== +// === APP BUILD === +// =========================================== + +var app = builder.Build(); + +app.UseCors("SignalR"); +app.UseSession(); + +var fruitBankHubEndPoint = $"/{FruitBankConstClient.DefaultHubName}"; +app.MapHub(fruitBankHubEndPoint, options => +{ + options.Transports = HttpTransportType.WebSockets; + options.WebSockets.CloseTimeout = TimeSpan.FromSeconds(10); + options.AllowStatefulReconnects = true; + options.TransportMaxBufferSize = 30_000_000; + options.ApplicationMaxBufferSize = 30_000_000; + options.TransportSendTimeout = TimeSpan.FromSeconds(60); +}); + +var loggerHubEndPoint = $"/{FruitBankConstClient.LoggerHubName}"; +app.MapHub(loggerHubEndPoint, options => +{ + options.AllowStatefulReconnects = false; +}); + +app.MapGet("/", () => "SANDBOX is running!"); +app.MapGet("/health", () => Results.Ok(new { status = "healthy", timestamp = DateTime.UtcNow })); + +// =========================================== +// === CONSOLE OUTPUT === +// =========================================== + +var finalConnectionString = app.Configuration.GetConnectionString("ConnectionString") ?? ""; +var databaseName = "Unknown"; +if (!string.IsNullOrEmpty(finalConnectionString)) +{ + var match = System.Text.RegularExpressions.Regex.Match(finalConnectionString, @"Initial Catalog=([^;]+)", System.Text.RegularExpressions.RegexOptions.IgnoreCase); + if (match.Success) + { + databaseName = match.Groups[1].Value; + } +} + +Console.Title = $"[SB] - {databaseName}"; + +Console.WriteLine("==========================================="); +Console.WriteLine($" FRUITBANK SANDBOX - {databaseName}"); +Console.WriteLine("==========================================="); +Console.WriteLine($" Database: {databaseName}"); +Console.WriteLine($" Base URL: http://localhost:59579"); +Console.WriteLine($" SignalR Hub: {fruitBankHubEndPoint}"); +Console.WriteLine($" Logger Hub: {loggerHubEndPoint}"); +Console.WriteLine("==========================================="); + +app.Run(); diff --git a/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/Services/NullAuthenticationPluginManager.cs b/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/Services/NullAuthenticationPluginManager.cs new file mode 100644 index 0000000..d65a42e --- /dev/null +++ b/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/Services/NullAuthenticationPluginManager.cs @@ -0,0 +1,30 @@ +using Nop.Core.Domain.Customers; +using Nop.Services.Authentication.External; +using Nop.Services.Plugins; + +namespace Mango.Sandbox.EndPoints.Services; + +public class NullAuthenticationPluginManager : IAuthenticationPluginManager +{ + public Task LoadPluginBySystemNameAsync(string systemName, Customer? customer = null, int storeId = 0) + => Task.FromResult(null); + + public Task> LoadAllPluginsAsync(Customer? customer = null, int storeId = 0) + => Task.FromResult>(new List()); + + public Task> LoadActivePluginsAsync(Customer? customer = null, int storeId = 0) + => Task.FromResult>(new List()); + + public Task> LoadActivePluginsAsync(List systemNames, Customer? customer = null, int storeId = 0) + => Task.FromResult>(new List()); + + public bool IsPluginActive(IExternalAuthenticationMethod plugin, List systemNames) => false; + + public bool IsPluginActive(IExternalAuthenticationMethod plugin) => false; + + public Task IsPluginActiveAsync(string systemName, Customer? customer = null, int storeId = 0) + => Task.FromResult(false); + + public Task GetPluginLogoUrlAsync(IExternalAuthenticationMethod plugin) + => Task.FromResult(string.Empty); +} diff --git a/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/Services/NullDiscountPluginManager.cs b/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/Services/NullDiscountPluginManager.cs new file mode 100644 index 0000000..5361a93 --- /dev/null +++ b/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/Services/NullDiscountPluginManager.cs @@ -0,0 +1,26 @@ +using Nop.Core.Domain.Customers; +using Nop.Core.Domain.Discounts; +using Nop.Services.Discounts; +using Nop.Services.Plugins; + +namespace Mango.Sandbox.EndPoints.Services; + +/// +/// Null implementation of IDiscountPluginManager for SANDBOX +/// +public class NullDiscountPluginManager : IDiscountPluginManager +{ + public Task LoadPluginBySystemNameAsync(string systemName, Customer? customer = null, int storeId = 0) + => Task.FromResult(null); + + public Task> LoadAllPluginsAsync(Customer? customer = null, int storeId = 0) + => Task.FromResult>(new List()); + + public Task> LoadActivePluginsAsync(List systemNames, Customer? customer = null, int storeId = 0) + => Task.FromResult>(new List()); + + public bool IsPluginActive(IDiscountRequirementRule plugin, List systemNames) => false; + + public Task GetPluginLogoUrlAsync(IDiscountRequirementRule plugin) + => Task.FromResult(string.Empty); +} diff --git a/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/Services/NullExchangeRatePluginManager.cs b/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/Services/NullExchangeRatePluginManager.cs new file mode 100644 index 0000000..b87ed19 --- /dev/null +++ b/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/Services/NullExchangeRatePluginManager.cs @@ -0,0 +1,31 @@ +using Nop.Core.Domain.Customers; +using Nop.Core.Domain.Directory; +using Nop.Services.Directory; +using Nop.Services.Plugins; + +namespace Mango.Sandbox.EndPoints.Services; + +/// +/// Null implementation of IExchangeRatePluginManager for SANDBOX +/// +public class NullExchangeRatePluginManager : IExchangeRatePluginManager +{ + public Task LoadPrimaryPluginAsync(Customer? customer = null, int storeId = 0) + => Task.FromResult(null); + + public bool IsPluginActive(IExchangeRateProvider exchangeRateProvider) => false; + + public Task LoadPluginBySystemNameAsync(string systemName, Customer? customer = null, int storeId = 0) + => Task.FromResult(null); + + public Task> LoadAllPluginsAsync(Customer? customer = null, int storeId = 0) + => Task.FromResult>(new List()); + + public bool IsPluginActive(IExchangeRateProvider plugin, List systemNames) => false; + + public Task> LoadActivePluginsAsync(List systemNames, Customer? customer = null, int storeId = 0) + => Task.FromResult>(new List()); + + public Task GetPluginLogoUrlAsync(IExchangeRateProvider plugin) + => Task.FromResult(string.Empty); +} diff --git a/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/Services/NullExternalAuthenticationService.cs b/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/Services/NullExternalAuthenticationService.cs new file mode 100644 index 0000000..5413328 --- /dev/null +++ b/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/Services/NullExternalAuthenticationService.cs @@ -0,0 +1,35 @@ +using Microsoft.AspNetCore.Mvc; +using Nop.Core.Domain.Customers; +using Nop.Services.Authentication.External; + +namespace Mango.Sandbox.EndPoints.Services; + +/// +/// Null implementation of IExternalAuthenticationService for SANDBOX +/// +public class NullExternalAuthenticationService : IExternalAuthenticationService +{ + public Task AuthenticateAsync(ExternalAuthenticationParameters parameters, string returnUrl = null!) + => Task.FromResult(new NotFoundResult()); + + public Task GetExternalAuthenticationRecordByIdAsync(int externalAuthenticationRecordId) + => Task.FromResult(null); + + public Task> GetCustomerExternalAuthenticationRecordsAsync(Customer customer) + => Task.FromResult>(new List()); + + public Task DeleteExternalAuthenticationRecordAsync(ExternalAuthenticationRecord externalAuthenticationRecord) + => Task.CompletedTask; + + public Task GetExternalAuthenticationRecordByExternalAuthenticationParametersAsync(ExternalAuthenticationParameters parameters) + => Task.FromResult(null); + + public Task AssociateExternalAccountWithUserAsync(Customer customer, ExternalAuthenticationParameters parameters) + => Task.CompletedTask; + + public Task GetUserByExternalAuthenticationParametersAsync(ExternalAuthenticationParameters parameters) + => Task.FromResult(null); + + public Task RemoveAssociationAsync(ExternalAuthenticationParameters parameters) + => Task.CompletedTask; +} diff --git a/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/Services/NullMultiFactorAuthenticationPluginManager.cs b/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/Services/NullMultiFactorAuthenticationPluginManager.cs new file mode 100644 index 0000000..ed080be --- /dev/null +++ b/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/Services/NullMultiFactorAuthenticationPluginManager.cs @@ -0,0 +1,36 @@ +using Nop.Core.Domain.Customers; +using Nop.Services.Authentication.MultiFactor; +using Nop.Services.Plugins; + +namespace Mango.Sandbox.EndPoints.Services; + +/// +/// Null implementation of IMultiFactorAuthenticationPluginManager for SANDBOX +/// +public class NullMultiFactorAuthenticationPluginManager : IMultiFactorAuthenticationPluginManager +{ + public Task LoadPluginBySystemNameAsync(string systemName, Customer? customer = null, int storeId = 0) + => Task.FromResult(null); + + public Task> LoadAllPluginsAsync(Customer? customer = null, int storeId = 0) + => Task.FromResult>(new List()); + + public Task> LoadActivePluginsAsync(Customer? customer = null, int storeId = 0) + => Task.FromResult>(new List()); + + public Task> LoadActivePluginsAsync(List systemNames, Customer? customer = null, int storeId = 0) + => Task.FromResult>(new List()); + + public Task HasActivePluginsAsync(Customer? customer = null, int storeId = 0) + => Task.FromResult(false); + + public bool IsPluginActive(IMultiFactorAuthenticationMethod plugin) => false; + + public bool IsPluginActive(IMultiFactorAuthenticationMethod plugin, List systemNames) => false; + + public Task IsPluginActiveAsync(string systemName, Customer? customer = null, int storeId = 0) + => Task.FromResult(false); + + public Task GetPluginLogoUrlAsync(IMultiFactorAuthenticationMethod plugin) + => Task.FromResult(string.Empty); +} diff --git a/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/Services/NullPaymentPluginManager.cs b/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/Services/NullPaymentPluginManager.cs new file mode 100644 index 0000000..23db962 --- /dev/null +++ b/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/Services/NullPaymentPluginManager.cs @@ -0,0 +1,36 @@ +using Nop.Core.Domain.Customers; +using Nop.Services.Payments; +using Nop.Services.Plugins; + +namespace Mango.Sandbox.EndPoints.Services; + +public class NullPaymentPluginManager : IPaymentPluginManager +{ + public Task LoadPluginBySystemNameAsync(string systemName, Customer? customer = null, int storeId = 0) + => Task.FromResult(null); + + public Task> LoadAllPluginsAsync(Customer? customer = null, int storeId = 0) + => Task.FromResult>(new List()); + + public Task> LoadActivePluginsAsync(Customer? customer = null, int storeId = 0, int filterByCountryId = 0) + => Task.FromResult>(new List()); + + public Task> LoadActivePluginsAsync(List systemNames, Customer? customer = null, int storeId = 0) + => Task.FromResult>(new List()); + + public bool IsPluginActive(IPaymentMethod plugin, List systemNames) => false; + + public bool IsPluginActive(IPaymentMethod plugin) => false; + + public Task IsPluginActiveAsync(string systemName, Customer? customer = null, int storeId = 0) + => Task.FromResult(false); + + public Task GetPluginLogoUrlAsync(IPaymentMethod plugin) + => Task.FromResult(string.Empty); + + public Task> GetRestrictedCountryIdsAsync(IPaymentMethod paymentMethod) + => Task.FromResult>(new List()); + + public Task SaveRestrictedCountriesAsync(IPaymentMethod paymentMethod, IList countryIds) + => Task.CompletedTask; +} diff --git a/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/Services/NullPickupPluginManager.cs b/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/Services/NullPickupPluginManager.cs new file mode 100644 index 0000000..6e375ad --- /dev/null +++ b/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/Services/NullPickupPluginManager.cs @@ -0,0 +1,30 @@ +using Nop.Core.Domain.Customers; +using Nop.Services.Plugins; +using Nop.Services.Shipping.Pickup; + +namespace Mango.Sandbox.EndPoints.Services; + +public class NullPickupPluginManager : IPickupPluginManager +{ + public Task LoadPluginBySystemNameAsync(string systemName, Customer? customer = null, int storeId = 0) + => Task.FromResult(null); + + public Task> LoadAllPluginsAsync(Customer? customer = null, int storeId = 0) + => Task.FromResult>(new List()); + + public Task> LoadActivePluginsAsync(Customer? customer = null, int storeId = 0, string filterByCountryId = null!) + => Task.FromResult>(new List()); + + public Task> LoadActivePluginsAsync(List systemNames, Customer? customer = null, int storeId = 0) + => Task.FromResult>(new List()); + + public bool IsPluginActive(IPickupPointProvider plugin, List systemNames) => false; + + public bool IsPluginActive(IPickupPointProvider plugin) => false; + + public Task IsPluginActiveAsync(string systemName, Customer? customer = null, int storeId = 0) + => Task.FromResult(false); + + public Task GetPluginLogoUrlAsync(IPickupPointProvider plugin) + => Task.FromResult(string.Empty); +} diff --git a/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/Services/NullSearchPluginManager.cs b/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/Services/NullSearchPluginManager.cs new file mode 100644 index 0000000..d9c496b --- /dev/null +++ b/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/Services/NullSearchPluginManager.cs @@ -0,0 +1,33 @@ +using Nop.Core.Domain.Customers; +using Nop.Services.Catalog; +using Nop.Services.Plugins; + +namespace Mango.Sandbox.EndPoints.Services; + +/// +/// Null implementation of ISearchPluginManager for SANDBOX +/// +public class NullSearchPluginManager : ISearchPluginManager +{ + public Task LoadPrimaryPluginAsync(Customer? customer = null, int storeId = 0) + => Task.FromResult(null); + + public bool IsPluginActive(ISearchProvider searchProvider) => false; + + public Task IsPluginActiveAsync(string systemName, Customer? customer = null, int storeId = 0) + => Task.FromResult(false); + + public Task LoadPluginBySystemNameAsync(string systemName, Customer? customer = null, int storeId = 0) + => Task.FromResult(null); + + public Task> LoadAllPluginsAsync(Customer? customer = null, int storeId = 0) + => Task.FromResult>(new List()); + + public bool IsPluginActive(ISearchProvider plugin, List systemNames) => false; + + public Task> LoadActivePluginsAsync(List systemNames, Customer? customer = null, int storeId = 0) + => Task.FromResult>(new List()); + + public Task GetPluginLogoUrlAsync(ISearchProvider plugin) + => Task.FromResult(string.Empty); +} diff --git a/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/Services/NullShippingPluginManager.cs b/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/Services/NullShippingPluginManager.cs new file mode 100644 index 0000000..d2980f5 --- /dev/null +++ b/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/Services/NullShippingPluginManager.cs @@ -0,0 +1,36 @@ +using Nop.Core.Domain.Customers; +using Nop.Services.Plugins; +using Nop.Services.Shipping; + +namespace Mango.Sandbox.EndPoints.Services; + +public class NullShippingPluginManager : IShippingPluginManager +{ + public Task LoadPluginBySystemNameAsync(string systemName, Customer? customer = null, int storeId = 0) + => Task.FromResult(null); + + public Task> LoadAllPluginsAsync(Customer? customer = null, int storeId = 0) + => Task.FromResult>(new List()); + + public Task> LoadActivePluginsAsync(Customer? customer = null, int storeId = 0, string filterByCountryId = null!) + => Task.FromResult>(new List()); + + public Task> LoadActivePluginsAsync(List systemNames, Customer? customer = null, int storeId = 0) + => Task.FromResult>(new List()); + + public bool IsPluginActive(IShippingRateComputationMethod plugin, List systemNames) => false; + + public bool IsPluginActive(IShippingRateComputationMethod plugin) => false; + + public Task IsPluginActiveAsync(string systemName, Customer? customer = null, int storeId = 0) + => Task.FromResult(false); + + public Task GetPluginLogoUrlAsync(IShippingRateComputationMethod plugin) + => Task.FromResult(string.Empty); + + public Task> GetRestrictedCountryIdsAsync(IShippingRateComputationMethod shippingMethod) + => Task.FromResult>(new List()); + + public Task SaveRestrictedCountriesAsync(IShippingRateComputationMethod shippingMethod, IList countryIds) + => Task.CompletedTask; +} diff --git a/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/Services/NullTaxPluginManager.cs b/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/Services/NullTaxPluginManager.cs new file mode 100644 index 0000000..f105bec --- /dev/null +++ b/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/Services/NullTaxPluginManager.cs @@ -0,0 +1,30 @@ +using Nop.Core.Domain.Customers; +using Nop.Services.Plugins; +using Nop.Services.Tax; + +namespace Mango.Sandbox.EndPoints.Services; + +public class NullTaxPluginManager : ITaxPluginManager +{ + public Task LoadPrimaryPluginAsync(Customer? customer = null, int storeId = 0) + => Task.FromResult(null); + + public Task LoadPluginBySystemNameAsync(string systemName, Customer? customer = null, int storeId = 0) + => Task.FromResult(null); + + public Task> LoadAllPluginsAsync(Customer? customer = null, int storeId = 0) + => Task.FromResult>(new List()); + + public Task> LoadActivePluginsAsync(List systemNames, Customer? customer = null, int storeId = 0) + => Task.FromResult>(new List()); + + public bool IsPluginActive(ITaxProvider plugin, List systemNames) => false; + + public bool IsPluginActive(ITaxProvider plugin) => false; + + public Task IsPluginActiveAsync(string systemName, Customer? customer = null, int storeId = 0) + => Task.FromResult(false); + + public Task GetPluginLogoUrlAsync(ITaxProvider plugin) + => Task.FromResult(string.Empty); +} diff --git a/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/Services/NullWidgetPluginManager.cs b/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/Services/NullWidgetPluginManager.cs new file mode 100644 index 0000000..c687b92 --- /dev/null +++ b/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/Services/NullWidgetPluginManager.cs @@ -0,0 +1,30 @@ +using Nop.Core.Domain.Customers; +using Nop.Services.Cms; +using Nop.Services.Plugins; + +namespace Mango.Sandbox.EndPoints.Services; + +public class NullWidgetPluginManager : IWidgetPluginManager +{ + public Task> LoadActivePluginsAsync(Customer? customer = null, int storeId = 0, string widgetZone = null!) + => Task.FromResult>(new List()); + + public Task LoadPluginBySystemNameAsync(string systemName, Customer? customer = null, int storeId = 0) + => Task.FromResult(null); + + public Task> LoadAllPluginsAsync(Customer? customer = null, int storeId = 0) + => Task.FromResult>(new List()); + + public Task> LoadActivePluginsAsync(List systemNames, Customer? customer = null, int storeId = 0) + => Task.FromResult>(new List()); + + public bool IsPluginActive(IWidgetPlugin plugin, List systemNames) => false; + + public bool IsPluginActive(IWidgetPlugin plugin) => false; + + public Task IsPluginActiveAsync(string systemName, Customer? customer = null, int storeId = 0) + => Task.FromResult(false); + + public Task GetPluginLogoUrlAsync(IWidgetPlugin plugin) + => Task.FromResult(string.Empty); +} diff --git a/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/appsettings.Development.json b/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/appsettings.Development.json new file mode 100644 index 0000000..0c208ae --- /dev/null +++ b/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/appsettings.json b/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/appsettings.json new file mode 100644 index 0000000..0032257 --- /dev/null +++ b/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/appsettings.json @@ -0,0 +1,13 @@ +{ + "ConnectionStrings": { + "ConnectionString": "Data Source=195.26.231.218;Initial Catalog=FruitBank_DEV;Integrated Security=False;Persist Security Info=False;User ID=sa;Password=v6f_?xNfg9N1;Trust Server Certificate=True" + }, + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning", + "Microsoft.AspNetCore.SignalR": "Debug" + } + }, + "AllowedHosts": "*" +} diff --git a/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/test-sandbox.ps1 b/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/test-sandbox.ps1 new file mode 100644 index 0000000..a8e0f3b --- /dev/null +++ b/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/test-sandbox.ps1 @@ -0,0 +1,81 @@ +# SANDBOX Tesztelő Script +# Futtatás: .\test-sandbox.ps1 + +$ErrorActionPreference = "Continue" +$projectPath = $PSScriptRoot +$url = "http://localhost:59579" + +Write-Host "=== SANDBOX TESZTELŐ ===" -ForegroundColor Cyan + +# 1. Build +Write-Host "`n[1/5] Building..." -ForegroundColor Yellow +$buildResult = dotnet build $projectPath --verbosity quiet 2>&1 +if ($LASTEXITCODE -ne 0) { + Write-Host "BUILD FAILED!" -ForegroundColor Red + $buildResult | Where-Object { $_ -match "error" } | ForEach-Object { Write-Host $_ -ForegroundColor Red } + exit 1 +} +Write-Host "Build OK" -ForegroundColor Green + +# 2. Ellenőrizzük, fut-e már +$existingProcess = Get-Process -Name "Mango.Sandbox.EndPoints" -ErrorAction SilentlyContinue +if ($existingProcess) { + Write-Host "`n[2/5] Stopping existing SANDBOX..." -ForegroundColor Yellow + Stop-Process -Name "Mango.Sandbox.EndPoints" -Force + Start-Sleep -Seconds 2 +} + +# 3. Indítás háttérben +Write-Host "`n[3/5] Starting SANDBOX..." -ForegroundColor Yellow +$process = Start-Process -FilePath "dotnet" -ArgumentList "run", "--project", $projectPath, "--urls", $url -PassThru -RedirectStandardOutput "$projectPath\sandbox-stdout.log" -RedirectStandardError "$projectPath\sandbox-stderr.log" +Start-Sleep -Seconds 10 + +# 4. Health check +Write-Host "`n[4/5] Testing endpoints..." -ForegroundColor Yellow + +try { + $response = Invoke-WebRequest -Uri "$url/" -UseBasicParsing -TimeoutSec 5 + if ($response.StatusCode -eq 200) { + Write-Host " / endpoint: OK" -ForegroundColor Green + } +} catch { + Write-Host " / endpoint: FAILED - $_" -ForegroundColor Red +} + +try { + $response = Invoke-WebRequest -Uri "$url/health" -UseBasicParsing -TimeoutSec 5 + if ($response.StatusCode -eq 200) { + Write-Host " /health endpoint: OK" -ForegroundColor Green + } +} catch { + Write-Host " /health endpoint: FAILED - $_" -ForegroundColor Red +} + +# SignalR negotiate teszt +try { + $response = Invoke-WebRequest -Uri "$url/fbHub/negotiate?negotiateVersion=1" -Method POST -UseBasicParsing -TimeoutSec 5 + Write-Host " SignalR negotiate: OK" -ForegroundColor Green +} catch { + Write-Host " SignalR negotiate: FAILED - $_" -ForegroundColor Red +} + +# 5. SignalR Hub hívás teszt (GetMeasuringUsers - tag 70) +Write-Host "`n[5/5] Testing SignalR Hub method..." -ForegroundColor Yellow +Write-Host " GetMeasuringUsers (tag 70) - Check SANDBOX console for logs" -ForegroundColor Gray + +# Hibák kiírása +Write-Host "`n=== STDERR LOG (last 50 lines) ===" -ForegroundColor Cyan +if (Test-Path "$projectPath\sandbox-stderr.log") { + Get-Content "$projectPath\sandbox-stderr.log" -Tail 50 | ForEach-Object { + if ($_ -match "error|fail|exception") { + Write-Host $_ -ForegroundColor Red + } elseif ($_ -match "warn") { + Write-Host $_ -ForegroundColor Yellow + } else { + Write-Host $_ -ForegroundColor Gray + } + } +} + +Write-Host "`n=== SANDBOX PID: $($process.Id) ===" -ForegroundColor Cyan +Write-Host "Leállítás: Stop-Process -Id $($process.Id)" -ForegroundColor Gray diff --git a/Tests/Mango.Sandbox/Mango.Sandbox.SignalRTestClient/Mango.Sandbox.SignalRTestClient.csproj b/Tests/Mango.Sandbox/Mango.Sandbox.SignalRTestClient/Mango.Sandbox.SignalRTestClient.csproj new file mode 100644 index 0000000..bd8e06d --- /dev/null +++ b/Tests/Mango.Sandbox/Mango.Sandbox.SignalRTestClient/Mango.Sandbox.SignalRTestClient.csproj @@ -0,0 +1,11 @@ + + + Exe + net9.0 + enable + enable + + + + + diff --git a/Tests/Mango.Sandbox/Mango.Sandbox.SignalRTestClient/Program.cs b/Tests/Mango.Sandbox/Mango.Sandbox.SignalRTestClient/Program.cs new file mode 100644 index 0000000..a0dcd51 --- /dev/null +++ b/Tests/Mango.Sandbox/Mango.Sandbox.SignalRTestClient/Program.cs @@ -0,0 +1,48 @@ +// SignalR Test Client - teszteli a SANDBOX kapcsolatot +using Microsoft.AspNetCore.SignalR.Client; +using System.Text.Json; + +Console.WriteLine("=== SANDBOX SignalR Test Client ==="); + +var hubUrl = "http://localhost:59579/fbHub"; +Console.WriteLine($"Connecting to: {hubUrl}"); + +var connection = new HubConnectionBuilder() + .WithUrl(hubUrl) + .WithAutomaticReconnect() + .Build(); + +connection.On("ReceiveMessage", (tag, data) => +{ + Console.WriteLine($"Received message - Tag: {tag}, Data length: {data?.Length ?? 0}"); +}); + +try +{ + await connection.StartAsync(); + Console.WriteLine($"Connected! State: {connection.State}"); + + // Teszt: GetMeasuringUsers (tag 70) hívása + Console.WriteLine("\nTesting GetMeasuringUsers (tag 70)..."); + + // A SignalR metódus hívása - a szerver "ReceiveMessage" metódusát hívjuk + // MessagePack formátumban küldjük az adatot + var requestData = new { Tag = 70, Data = Array.Empty() }; + + await connection.InvokeAsync("ReceiveMessage", 70, Array.Empty()); + + Console.WriteLine("Message sent! Waiting for response..."); + await Task.Delay(3000); + + Console.WriteLine("\nTest completed!"); +} +catch (Exception ex) +{ + Console.WriteLine($"Error: {ex.Message}"); + Console.WriteLine($"Stack: {ex.StackTrace}"); +} +finally +{ + await connection.StopAsync(); + Console.WriteLine("Disconnected."); +}