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 index 0c2b8e2..ce96e04 100644 --- 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 @@ -1,4 +1,4 @@ - + net9.0 @@ -10,10 +10,74 @@ + + + + + + + + + + ..\..\..\..\FruitBankHybridApp\FruitBank.Common.Server\bin\Debug\net9.0\AyCode.Core.dll + + + ..\..\..\..\..\..\Aycode\Source\AyCode.Core\AyCode.Services.Server.Tests\bin\FruitBank\Debug\net9.0\AyCode.Core.Server.dll + + + ..\..\..\..\..\..\Aycode\Source\AyCode.Core\AyCode.Services.Server.Tests\bin\FruitBank\Debug\net9.0\AyCode.Core.Tests.dll + + + ..\..\..\..\..\..\Aycode\Source\AyCode.Core\AyCode.Services.Server.Tests\bin\FruitBank\Debug\net9.0\AyCode.Database.dll + + + ..\..\..\..\..\..\Aycode\Source\AyCode.Core\AyCode.Services.Server.Tests\bin\FruitBank\Debug\net9.0\AyCode.Database.Tests.dll + + + ..\..\..\..\..\..\Aycode\Source\AyCode.Core\AyCode.Services.Server.Tests\bin\FruitBank\Debug\net9.0\AyCode.Entities.dll + + + ..\..\..\..\..\..\Aycode\Source\AyCode.Core\AyCode.Services.Server.Tests\bin\FruitBank\Debug\net9.0\AyCode.Entities.Server.dll + + + ..\..\..\..\..\..\Aycode\Source\AyCode.Core\AyCode.Services.Server.Tests\bin\FruitBank\Debug\net9.0\AyCode.Interfaces.dll + + + ..\..\..\..\..\..\Aycode\Source\AyCode.Core\AyCode.Services.Server.Tests\bin\FruitBank\Debug\net9.0\AyCode.Interfaces.Server.dll + + + ..\..\..\..\..\..\Aycode\Source\AyCode.Core\AyCode.Services.Server.Tests\bin\FruitBank\Debug\net9.0\AyCode.Models.dll + + + ..\..\..\..\..\..\Aycode\Source\AyCode.Core\AyCode.Services.Server.Tests\bin\FruitBank\Debug\net9.0\AyCode.Models.Server.dll + + + ..\..\..\..\FruitBankHybridApp\FruitBank.Common.Server\bin\Debug\net9.0\AyCode.Services.dll + + + ..\..\..\..\..\..\Aycode\Source\AyCode.Core\AyCode.Services.Server.Tests\bin\FruitBank\Debug\net9.0\AyCode.Services.Server.dll + + + ..\..\..\..\..\..\Aycode\Source\AyCode.Core\AyCode.Services.Server.Tests\bin\FruitBank\Debug\net9.0\AyCode.Services.Server.Tests.dll + + + ..\..\..\..\..\..\Aycode\Source\AyCode.Core\AyCode.Services.Server.Tests\bin\FruitBank\Debug\net9.0\AyCode.Services.Tests.dll + + + ..\..\..\..\..\..\Aycode\Source\AyCode.Core\AyCode.Services.Server.Tests\bin\FruitBank\Debug\net9.0\AyCode.Utils.dll + + + ..\..\..\..\..\..\Aycode\Source\AyCode.Core\AyCode.Services.Server.Tests\bin\FruitBank\Debug\net9.0\AyCode.Utils.Server.dll + + + ..\..\..\..\FruitBankHybridApp\FruitBank.Common.Server\bin\Debug\net9.0\FruitBank.Common.dll + + + diff --git a/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints.Tests/SignalRClientSandbox.cs b/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints.Tests/SignalRClientSandbox.cs new file mode 100644 index 0000000..7b33e03 --- /dev/null +++ b/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints.Tests/SignalRClientSandbox.cs @@ -0,0 +1,30 @@ +using AyCode.Core.Loggers; +using AyCode.Services.SignalRs; +using Mango.Sandbox.EndPoints; + +namespace Mango.Sandbox.EndPoints.Tests; + +/// +/// SignalR kliens a Sandbox teszteléshez. +/// Az AcSignalRClientBase-bõl származik, a GetByIdAsync, GetAllAsync, PostDataAsync, GetAllIntoAsync metódusokat örökli. +/// +public class SignalRClientSandbox : AcSignalRClientBase +{ + public SignalRClientSandbox(string hubUrl) + : base(hubUrl, new Logger()) + { + } + + protected override SignalResponseJsonMessage DeserializeResponseMsgPack(byte[] messageBytes) + { + var responseJsonMessage = base.DeserializeResponseMsgPack(messageBytes); + Console.WriteLine(responseJsonMessage.ResponseDataJson); + return responseJsonMessage; + } + + protected override Task MessageReceived(int messageTag, byte[] messageBytes) + { + Console.WriteLine($"[SignalRClientSandbox] Push message received: tag={messageTag}"); + return Task.CompletedTask; + } +} diff --git a/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints.Tests/SignalRClientToEndpointTest.cs b/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints.Tests/SignalRClientToEndpointTest.cs new file mode 100644 index 0000000..0ba373e --- /dev/null +++ b/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints.Tests/SignalRClientToEndpointTest.cs @@ -0,0 +1,457 @@ +using AyCode.Services.SignalRs; +using Mango.Sandbox.EndPoints; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace Mango.Sandbox.EndPoints.Tests; + +/// +/// Komplex SignalR tesztek a SignalRClientSandbox használatával. +/// Az AcSignalRClientBase GetByIdAsync, GetAllAsync, PostDataAsync, GetAllIntoAsync metódusait teszteli. +/// FONTOS: A SANDBOX-ot manuálisan kell elindítani a tesztek futtatása elÅ‘tt! +/// +[TestClass] +public class SignalRClientToEndpointTest +{ + private static readonly string HubUrl = "http://localhost:59579/fbHub"; + private static SignalRClientSandbox _client = null!; + + [ClassInitialize] + public static async Task ClassInitialize(TestContext context) + { + // Sandbox ellenÅ‘rzés + //using var httpClient = new HttpClient { Timeout = TimeSpan.FromSeconds(5) }; + //try + //{ + // var response = await httpClient.GetAsync("http://localhost:59579/health"); + // Assert.IsTrue(response.IsSuccessStatusCode, + // "SANDBOX not running! Start: dotnet run --project Mango.Sandbox.EndPoints --urls http://localhost:59579"); + //} + //catch (Exception ex) + //{ + // Assert.Fail($"SANDBOX not running! {ex.Message}"); + //} + + _client = new SignalRClientSandbox(HubUrl); + await _client.StartConnection(); + } + + [ClassCleanup] + public static async Task ClassCleanup() + { + if (_client != null) + await _client.StopConnection(); + } + + #region GetAllAsync Tesztek - Paraméter nélkül + + [TestMethod] + public async Task GetAllAsync_NoParams_ReturnsTestItems() + { + // Act - GetAllAsync(tag) + var result = await _client.GetAllAsync>(TestSignalRTags.GetTestItems); + + // Assert + Assert.IsNotNull(result); + Assert.IsTrue(result.Count > 0); + Console.WriteLine($"[GetAllAsync] Received {result.Count} items"); + } + + [TestMethod] + public async Task GetAllAsync_NoParams_Callback_ReturnsTestItems() + { + // Arrange + List? receivedItems = null; + var tcs = new TaskCompletionSource(); + + // Act - GetAllAsync(tag, callback) + await _client.GetAllAsync>(TestSignalRTags.GetTestItems, response => + { + receivedItems = response.ResponseData; + tcs.SetResult(true); + return Task.CompletedTask; + }); + + await Task.WhenAny(tcs.Task, Task.Delay(5000)); + + // Assert + Assert.IsNotNull(receivedItems); + Assert.IsTrue(receivedItems.Count > 0); + } + + [TestMethod] + public async Task GetAllAsync_HandleNoParams_ReturnsOk() + { + // Act - paraméter nélküli metódus + var result = await _client.GetAllAsync(TestSignalRTags.NoParams); + + // Assert + Assert.IsNotNull(result); + Assert.AreEqual("OK", result); + } + + #endregion + + #region GetByIdAsync Tesztek - Egyetlen ID + + [TestMethod] + public async Task GetByIdAsync_SingleInt_ReturnsFormattedString() + { + // Act - GetByIdAsync(tag, id) + var result = await _client.GetByIdAsync(TestSignalRTags.SingleIntParam, 42); + + // Assert + Assert.IsNotNull(result); + Assert.AreEqual("Received: 42", result); + } + + [TestMethod] + public async Task GetByIdAsync_String_ReturnsEcho() + { + // Act + var result = await _client.GetByIdAsync(TestSignalRTags.StringParam, "Hello World"); + + // Assert + Assert.IsNotNull(result); + Assert.AreEqual("Echo: Hello World", result); + } + + [TestMethod] + public async Task GetByIdAsync_Bool_ReturnsTrue() + { + // Act + var result = await _client.GetByIdAsync(TestSignalRTags.BoolParam, true); + + // Assert + Assert.IsTrue(result); + } + + [TestMethod] + public async Task GetByIdAsync_Guid_ReturnsSameGuid() + { + // Arrange + var guid = Guid.NewGuid(); + + // Act + var result = await _client.GetByIdAsync(TestSignalRTags.GuidParam, guid); + + // Assert + Assert.AreEqual(guid, result); + } + + [TestMethod] + public async Task GetByIdAsync_Decimal_ReturnsDoubled() + { + // Act + var result = await _client.GetByIdAsync(TestSignalRTags.DecimalParam, 123.45m); + + // Assert + Assert.AreEqual(246.90m, result); + } + + [TestMethod] + public async Task GetByIdAsync_Long_ReturnsSameLong() + { + // Act + var result = await _client.GetByIdAsync(TestSignalRTags.LongParam, 9223372036854775807L); + + // Assert + Assert.AreEqual(9223372036854775807L, result); + } + + [TestMethod] + public async Task GetByIdAsync_Double_ReturnsSameDouble() + { + // Act + var result = await _client.GetByIdAsync(TestSignalRTags.DoubleParam, 3.14159); + + // Assert + Assert.AreEqual(3.14159, result, 0.00001); + } + + [TestMethod] + public async Task GetByIdAsync_Enum_ReturnsSameEnum() + { + // Act + var result = await _client.GetByIdAsync(TestSignalRTags.EnumParam, (int)TestStatus.Active); + + // Assert + Assert.AreEqual(TestStatus.Active, result); + } + + [TestMethod] + public async Task GetByIdAsync_SingleInt_Callback_ReturnsFormattedString() + { + // Arrange + string? receivedResult = null; + var tcs = new TaskCompletionSource(); + + // Act - GetByIdAsync(tag, callback, id) + await _client.GetByIdAsync(TestSignalRTags.SingleIntParam, response => + { + receivedResult = response.ResponseData; + tcs.SetResult(true); + return Task.CompletedTask; + }, 100); + + await Task.WhenAny(tcs.Task, Task.Delay(5000)); + + // Assert + Assert.IsNotNull(receivedResult); + Assert.AreEqual("Received: 100", receivedResult); + } + + #endregion + + #region GetByIdAsync Tesztek - Több ID (object[]) + + [TestMethod] + public async Task GetByIdAsync_TwoInts_ReturnsSum() + { + // Act - GetByIdAsync(tag, ids[]) + var result = await _client.GetByIdAsync(TestSignalRTags.TwoIntParams, new object[] { 10, 20 }); + + // Assert + Assert.AreEqual(30, result); + } + + [TestMethod] + public async Task GetByIdAsync_MultipleTypes_ReturnsFormattedString() + { + // Act + var result = await _client.GetByIdAsync(TestSignalRTags.MultipleTypesParams, new object[] { true, "test", 123 }); + + // Assert + Assert.IsNotNull(result); + Assert.AreEqual("True-test-123", result); + } + + [TestMethod] + public async Task GetByIdAsync_FiveParams_ReturnsFormattedString() + { + // Arrange + var guid = Guid.NewGuid(); + + // Act + var result = await _client.GetByIdAsync(TestSignalRTags.FiveParams, new object[] { 1, "text", true, guid, 99.99m }); + + // Assert + Assert.IsNotNull(result); + Assert.AreEqual($"1-text-True-{guid}-99.99", result); + } + + [TestMethod] + public async Task GetByIdAsync_TwoInts_Callback_ReturnsSum() + { + // Arrange + int? receivedResult = null; + var tcs = new TaskCompletionSource(); + + // Act - GetByIdAsync(tag, callback, ids[]) + await _client.GetByIdAsync(TestSignalRTags.TwoIntParams, response => + { + receivedResult = response.ResponseData; + tcs.SetResult(true); + return Task.CompletedTask; + }, new object[] { 5, 7 }); + + await Task.WhenAny(tcs.Task, Task.Delay(5000)); + + // Assert + Assert.IsNotNull(receivedResult); + Assert.AreEqual(12, receivedResult.Value); + } + + #endregion + + #region GetAllAsync Tesztek - ContextParams-szal + + [TestMethod] + public async Task GetAllAsync_WithContextParams_IntArray_ReturnsDoubled() + { + // Act - GetAllAsync(tag, contextParams[]) + var result = await _client.GetAllAsync(TestSignalRTags.IntArrayParam, new object[] { new[] { 1, 2, 3 } }); + + // Assert + Assert.IsNotNull(result); + CollectionAssert.AreEqual(new[] { 2, 4, 6 }, result); + } + + [TestMethod] + public async Task GetAllAsync_WithContextParams_StringList_ReturnsUppercased() + { + // Act + var result = await _client.GetAllAsync>(TestSignalRTags.StringListParam, new object[] { new List { "apple", "banana" } }); + + // Assert + Assert.IsNotNull(result); + CollectionAssert.AreEqual(new List { "APPLE", "BANANA" }, result); + } + + [TestMethod] + public async Task GetAllAsync_WithContextParams_Callback_IntArray() + { + // Arrange + int[]? receivedResult = null; + var tcs = new TaskCompletionSource(); + + // Act - GetAllAsync(tag, callback, contextParams[]) + await _client.GetAllAsync(TestSignalRTags.IntArrayParam, response => + { + receivedResult = response.ResponseData; + tcs.SetResult(true); + return Task.CompletedTask; + }, new object[] { new[] { 5, 10, 15 } }); + + await Task.WhenAny(tcs.Task, Task.Delay(5000)); + + // Assert + Assert.IsNotNull(receivedResult); + CollectionAssert.AreEqual(new[] { 10, 20, 30 }, receivedResult); + } + + #endregion + + #region PostDataAsync Tesztek - Komplex Objektumok + + [TestMethod] + public async Task PostDataAsync_TestEchoRequest_ReturnsEchoResponse() + { + // Arrange + var request = new TestEchoRequest { Id = 42, Name = "TestName" }; + + // Act - PostDataAsync(tag, data) + var result = await _client.PostDataAsync(TestSignalRTags.EchoTag, request); + + // Assert + Assert.IsNotNull(result); + Assert.AreEqual(42, result.Id); + Assert.AreEqual("TestName", result.Name); + Assert.IsTrue(result.EchoedSuccessfully); + } + + [TestMethod] + public async Task PostDataAsync_TestOrderItem_ReturnsProcessedItem() + { + // Arrange + var item = new TestOrderItem { Id = 1, ProductName = "TestProduct", Quantity = 5, UnitPrice = 10m }; + + // Act + var result = await _client.PostDataAsync(TestSignalRTags.TestOrderItemParam, item); + //await Task.Delay(1000); + // Assert + Assert.IsNotNull(result); + //Assert.AreEqual("Processed: TestProduct", result.ProductName); + Assert.AreEqual(item.Quantity * 2, result.Quantity); // doubled + } + + [TestMethod] + public async Task PostDataAsync_TestOrder_ReturnsNestedOrder() + { + // Arrange + var order = new TestOrder + { + Id = 100, + CustomerName = "Test Customer", + OrderDate = DateTime.UtcNow, + Status = TestStatus.Active, + Items = [new() { Id = 1, ProductName = "Item1", Quantity = 2, UnitPrice = 10m }] + }; + + // Act + var result = await _client.PostDataAsync(TestSignalRTags.TestOrderParam, order); + + // Assert + Assert.IsNotNull(result); + Assert.AreEqual(100, result.Id); + Assert.AreEqual("Test Customer", result.CustomerName); + Assert.AreEqual(1, result.Items.Count); + } + + [TestMethod] + public async Task PostDataAsync_SharedTag_ReturnsTag() + { + // Arrange + var tag = new SharedTag { Id = 1, Name = "Tag1", Description = "Desc", IsActive = true }; + + // Act + var result = await _client.PostDataAsync(TestSignalRTags.SharedTagParam, tag); + + // Assert + Assert.IsNotNull(result); + Assert.AreEqual("Tag1", result.Name); + Assert.AreEqual("Desc", result.Description); + } + + [TestMethod] + public async Task PostDataAsync_Callback_TestEchoRequest() + { + // Arrange + var request = new TestEchoRequest { Id = 99, Name = "CallbackTest" }; + TestEchoResponse? receivedResult = null; + var tcs = new TaskCompletionSource(); + + // Act - PostDataAsync(tag, data, callback) + await _client.PostDataAsync(TestSignalRTags.EchoTag, request, response => + { + receivedResult = response.ResponseData; + tcs.SetResult(true); + return Task.CompletedTask; + }); + + await Task.WhenAny(tcs.Task, Task.Delay(5000)); + + // Assert + Assert.IsNotNull(receivedResult); + Assert.AreEqual(99, receivedResult.Id); + } + + #endregion + + #region Edge Case Tesztek + + [TestMethod] + public async Task GetByIdAsync_EmptyString_ReturnsEchoOfEmpty() + { + // Act + var result = await _client.GetByIdAsync(TestSignalRTags.StringParam, ""); + + // Assert + Assert.IsNotNull(result); + Assert.AreEqual("Echo: ", result); + } + + [TestMethod] + public async Task GetByIdAsync_Zero_ReturnsFormattedString() + { + // Act + var result = await _client.GetByIdAsync(TestSignalRTags.SingleIntParam, 0); + + // Assert + Assert.IsNotNull(result); + Assert.AreEqual("Received: 0", result); + } + + [TestMethod] + public async Task GetByIdAsync_NegativeInt_ReturnsFormattedString() + { + // Act + var result = await _client.GetByIdAsync(TestSignalRTags.SingleIntParam, -42); + + // Assert + Assert.IsNotNull(result); + Assert.AreEqual("Received: -42", result); + } + + [TestMethod] + public async Task GetAllAsync_EmptyArray_ReturnsEmptyArray() + { + // Act + var result = await _client.GetAllAsync(TestSignalRTags.IntArrayParam, new object[] { Array.Empty() }); + + // Assert + Assert.IsNotNull(result); + Assert.AreEqual(0, result.Length); + } + + #endregion +} \ No newline at end of file diff --git a/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints.Tests/SignalREndpointSimpleTests.cs b/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints.Tests/SignalREndpointSimpleTests.cs new file mode 100644 index 0000000..1520649 --- /dev/null +++ b/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints.Tests/SignalREndpointSimpleTests.cs @@ -0,0 +1,210 @@ +using AyCode.Core.Extensions; +using AyCode.Services.SignalRs; +using FruitBank.Common.SignalRs; +using Mango.Sandbox.EndPoints; +using MessagePack; +using Microsoft.AspNetCore.SignalR.Client; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System.Text; +using MessagePack.Resolvers; + +namespace Mango.Sandbox.EndPoints.Tests; + +/// +/// Alacsony szintû SignalR tesztek - közvetlen HubConnection használatával. +/// FONTOS: A SANDBOX-ot manuálisan kell elindítani a tesztek futtatása elõtt! +/// +[TestClass] +public class SignalREndpointSimpleTests +{ + private static readonly string SandboxUrl = "http://localhost:59579"; + private static readonly string HubUrl = $"{SandboxUrl}/fbHub"; + + [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 not running! Start: dotnet run --project Mango.Sandbox.EndPoints --urls http://localhost:59579"); + } + catch (Exception ex) + { + Assert.Fail($"SANDBOX not running! {ex.Message}"); + } + } + + #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); + } + + [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); + } + + [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 Low-Level SignalR Tests + + [TestMethod] + public async Task SignalR_Ping_ReturnsResponse() + { + await SignalRClientHelper(TestSignalRTags.PingTag, "Hello SignalR!", "Ping", response => + { + Assert.IsNotNull(response); + var pingResponse = response.JsonTo(); + Assert.IsNotNull(pingResponse); + Console.WriteLine($"[Ping] Message: {pingResponse.Message}"); + }); + } + + [TestMethod] + public async Task SignalR_Echo_ReturnsEchoedData() + { + var request = new TestEchoRequest { Id = 42, Name = "TestName" }; + await SignalRClientHelper(TestSignalRTags.EchoTag, request, "Echo", response => + { + Assert.IsNotNull(response); + var echoResponse = response.JsonTo(); + Assert.IsNotNull(echoResponse); + Assert.AreEqual(42, echoResponse.Id); + }); + } + + [TestMethod] + public async Task SignalR_GetTestItems_ReturnsItemList() + { + await SignalRClientHelper(TestSignalRTags.GetTestItems, null, "GetTestItems", response => + { + Assert.IsNotNull(response); + var items = response.JsonTo>(); + Assert.IsNotNull(items); + Assert.IsTrue(items.Count > 0); + }); + } + + #endregion + + #region Helper Methods + + private async Task SignalRClientHelper(int tag, object? parameter, string endpointName, Action? validateResponse = null) + { + var connection = new HubConnectionBuilder() + .WithUrl(HubUrl) + .Build(); + + string? receivedJson = null; + var responseReceived = new TaskCompletionSource(); + + connection.On("OnReceiveMessage", (responseTag, data, requestId) => + { + if (data != null && data.Length > 0) + { + try + { + var options = MessagePack.Resolvers.ContractlessStandardResolver.Options; + var response = MessagePackSerializer.Deserialize(data, options); + receivedJson = response?.ResponseData; + } + catch + { + receivedJson = Encoding.UTF8.GetString(data); + } + } + responseReceived.TrySetResult(true); + }); + + try + { + await connection.StartAsync(); + Assert.AreEqual(HubConnectionState.Connected, connection.State); + + byte[]? requestData = CreateRequestData(parameter); + await connection.InvokeAsync("OnReceiveMessage", tag, requestData, (int?)null); + + var completed = await Task.WhenAny(responseReceived.Task, Task.Delay(5000)); + if (completed == responseReceived.Task) + { + validateResponse?.Invoke(receivedJson); + } + else + { + Assert.Fail($"[{endpointName}] Timeout"); + } + } + finally + { + if (connection.State == HubConnectionState.Connected) + await connection.StopAsync(); + } + } + + private static byte[]? CreateRequestData(object? parameter) + { + if (parameter == null) return null; + + var isPrimitive = parameter is string or int or long or double or float or decimal or bool or DateTime; + + if (isPrimitive) + { + var idMessage = new IdMessage(parameter); + return new SignalPostJsonDataMessage(idMessage).ToMessagePack(ContractlessStandardResolver.Options); + } + else + { + return new SignalPostJsonDataMessage(parameter).ToMessagePack(ContractlessStandardResolver.Options); + } + } + + #endregion +} + +/// +/// Wrapper a Task eredményekhez - a szerver Task-ot ad vissza {"Result":...} formátumban +/// +public class TaskResultWrapper +{ + public T? Result { get; set; } +} diff --git a/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints.Tests/SignalREndpointTests.cs b/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints.Tests/SignalREndpointTests.cs deleted file mode 100644 index 76a7aa6..0000000 --- a/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints.Tests/SignalREndpointTests.cs +++ /dev/null @@ -1,218 +0,0 @@ -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.Tests/SignalREndpointWithNopEnvTests.cs b/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints.Tests/SignalREndpointWithNopEnvTests.cs new file mode 100644 index 0000000..9c11f96 --- /dev/null +++ b/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints.Tests/SignalREndpointWithNopEnvTests.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 SignalREndpointWithNopEnvTests +{ + 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/DevAdminSignalRHubSandbox.cs b/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/DevAdminSignalRHubSandbox.cs new file mode 100644 index 0000000..97c4ab5 --- /dev/null +++ b/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/DevAdminSignalRHubSandbox.cs @@ -0,0 +1,42 @@ +using AyCode.Core.Enums; +using AyCode.Core.Loggers; +using AyCode.Models.Server.DynamicMethods; +using AyCode.Services.Server.SignalRs; +using AyCode.Services.SignalRs; +using FruitBank.Common.Interfaces; +using FruitBank.Common.Loggers; +using FruitBank.Common.Server.Interfaces; +using FruitBank.Common.Server.Services.SignalRs; +using FruitBank.Common.SignalRs; +using Mango.Nop.Core.Loggers; +using Microsoft.Extensions.Configuration; +//using Nop.Plugin.Misc.FruitBankPlugin.Controllers; + +namespace Mango.Sandbox.EndPoints; + +/// +/// Egyszerûsített SignalR Hub a teszteléshez. +/// Ez a Hub nem függ a 3 eredeti endpoint-tól (IFruitBankDataControllerServer, ICustomOrderSignalREndpointServer, IStockSignalREndpointServer). +/// +public class DevAdminSignalRHubSandbox : AcWebSignalRHubWithSessionBase> +{ + public DevAdminSignalRHubSandbox(IConfiguration configuration, ITestSignalREndpointServer testSignalREndpoint, IEnumerable logWriters) + : base(configuration, new Logger(logWriters.ToArray())) + { + DynamicMethodCallModels.Add(new AcDynamicMethodCallModel(testSignalREndpoint)); + + } + + protected override Task SendMessageToClient(IAcSignalRHubItemServer sendTo, int messageTag, ISignalRMessage message, int? requestId = null) + { + Console.WriteLine(((SignalResponseJsonMessage)message).ResponseDataJson); + + return base.SendMessageToClient(sendTo, messageTag, message, requestId); + } +} + +// =========================================== +// === EREDETI KÓD - KIKOMMENTEZVE === +// =========================================== +// A helyes using: FruitBank.Common.Server.Services.SignalRs (nem AyCode.Services.SignalRs!) +// Az AcWebSignalRHubWithSessionBase a FruitBank.Common.Server projektben van definiálva. diff --git a/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/Logger.cs b/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/Logger.cs new file mode 100644 index 0000000..7f5ea04 --- /dev/null +++ b/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/Logger.cs @@ -0,0 +1,40 @@ +using AyCode.Core.Enums; +using AyCode.Core.Loggers; + +namespace Mango.Sandbox.EndPoints; + + +public interface ILogger : ILogger +{ +} +public interface ILogger : IAcLoggerBase +{ +} + +public class Logger : Logger, ILogger +{ + //public Logger() : base(typeof(TCategory).Name) + //{ } + + public Logger(params IAcLogWriterBase[] logWriters) : base(typeof(TCategory).Name, logWriters) + { } + + public Logger(AppType appType, AyCode.Core.Loggers.LogLevel logLevel, params IAcLogWriterBase[] logWriters) : base(appType, logLevel, typeof(TCategory).Name, logWriters) + { } +} + +public class Logger : AcLoggerBase, ILogger +{ + public Logger(params IAcLogWriterBase[] logWriters) : this(null, logWriters) + { } + + public Logger(string? categoryName) : base(categoryName) + { } + + public Logger(string? categoryName, params IAcLogWriterBase[] logWriters) : base(categoryName, logWriters) + { } + + public Logger(AppType appType, AyCode.Core.Loggers.LogLevel logLevel, string? categoryName, params IAcLogWriterBase[] logWriters) : base(appType, logLevel, categoryName, logWriters) + { } +} + diff --git a/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/Mango.Sandbox.EndPoints.csproj b/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/Mango.Sandbox.EndPoints.csproj index 7337993..a8a0166 100644 --- a/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/Mango.Sandbox.EndPoints.csproj +++ b/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/Mango.Sandbox.EndPoints.csproj @@ -1,10 +1,10 @@ - + net9.0 enable enable - + false + H:\Applications\Aycode\Source\AyCode.Core\ - + - + - + @@ -76,63 +78,57 @@ - - - + + + + + + - - - - $(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 + $(AyCodeRoot)AyCode.Core\bin\FruitBank\Debug\net9.0\AyCode.Core.dll - $(FruitBankHybridRoot)FruitBank.Common.Server\bin\Debug\net9.0\AyCode.Core.Server.dll + $(AyCodeRoot)AyCode.Core.Server\bin\FruitBank\Debug\net9.0\AyCode.Core.Server.dll - $(FruitBankHybridRoot)FruitBank.Common.Server\bin\Debug\net9.0\AyCode.Database.dll + $(AyCodeRoot)AyCode.Database\bin\FruitBank\Debug\net9.0\AyCode.Database.dll - $(FruitBankHybridRoot)FruitBank.Common.Server\bin\Debug\net9.0\AyCode.Entities.dll + $(AyCodeRoot)AyCode.Entities\bin\FruitBank\Debug\net9.0\AyCode.Entities.dll - $(FruitBankHybridRoot)FruitBank.Common.Server\bin\Debug\net9.0\AyCode.Entities.Server.dll + $(AyCodeRoot)AyCode.Entities.Server\bin\FruitBank\Debug\net9.0\AyCode.Entities.Server.dll - $(FruitBankHybridRoot)FruitBank.Common.Server\bin\Debug\net9.0\AyCode.Interfaces.dll + $(AyCodeRoot)AyCode.Interfaces\bin\FruitBank\Debug\net9.0\AyCode.Interfaces.dll - $(FruitBankHybridRoot)FruitBank.Common.Server\bin\Debug\net9.0\AyCode.Interfaces.Server.dll + $(AyCodeRoot)AyCode.Interfaces.Server\bin\FruitBank\Debug\net9.0\AyCode.Interfaces.Server.dll - $(FruitBankHybridRoot)FruitBank.Common.Server\bin\Debug\net9.0\AyCode.Models.Server.dll + $(AyCodeRoot)AyCode.Models.Server\bin\FruitBank\Debug\net9.0\AyCode.Models.Server.dll - $(FruitBankHybridRoot)FruitBank.Common.Server\bin\Debug\net9.0\AyCode.Services.dll + $(AyCodeRoot)AyCode.Services\bin\FruitBank\Debug\net9.0\AyCode.Services.dll - $(FruitBankHybridRoot)FruitBank.Common.Server\bin\Debug\net9.0\AyCode.Services.Server.dll + $(AyCodeRoot)AyCode.Services.Server\bin\FruitBank\Debug\net9.0\AyCode.Services.Server.dll - $(FruitBankHybridRoot)FruitBank.Common.Server\bin\Debug\net9.0\AyCode.Utils.dll + $(AyCodeRoot)AyCode.Utils\bin\FruitBank\Debug\net9.0\AyCode.Utils.dll + $(FruitBankHybridRoot)FruitBank.Common.Server\bin\Debug\net9.0\FruitBank.Common.dll diff --git a/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/Program.cs b/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/Program.cs index c674ff9..5eac8f7 100644 --- a/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/Program.cs +++ b/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/Program.cs @@ -1,161 +1,17 @@ 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 Mango.Sandbox.EndPoints; 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Ó === +// === MINIMÁLIS KONFIGURÁCIÓ A SIGNALR HUB TESZTELÉSÉHEZ === // =========================================== -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"); +Console.WriteLine("[SANDBOX] Starting minimal SignalR Hub test configuration..."); // =========================================== // === CORS === @@ -184,489 +40,26 @@ builder.Host.UseDefaultServiceProvider(options => 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(); +builder.Services.AddDistributedMemoryCache(); // IDistributedCache a Session-höz +builder.Services.AddSession(); // =========================================== -// === APP SETTINGS === +// === LOGGER - Csak ConsoleLogWriter a teszteléshez === // =========================================== -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(); +// =========================================== +// === TESZT ENDPOINT === +// =========================================== -// 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(); +builder.Services.AddScoped(); // =========================================== // === SIGNALR KONFIGURÁCIÓ === @@ -690,8 +83,14 @@ var app = builder.Build(); app.UseCors("SignalR"); app.UseSession(); +// =========================================== +// === SIGNALR HUB REGISZTRÁCIÓ === +// =========================================== + var fruitBankHubEndPoint = $"/{FruitBankConstClient.DefaultHubName}"; -app.MapHub(fruitBankHubEndPoint, options => + +// SANDBOX TESZT HUB - egyszerûsített, nincs Nop függõség +app.MapHub(fruitBankHubEndPoint, options => { options.Transports = HttpTransportType.WebSockets; options.WebSockets.CloseTimeout = TimeSpan.FromSeconds(10); @@ -714,23 +113,11 @@ app.MapGet("/health", () => Results.Ok(new { status = "healthy", timestamp = Dat // === 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.Title = "[SB] - SignalR Test"; Console.WriteLine("==========================================="); -Console.WriteLine($" FRUITBANK SANDBOX - {databaseName}"); +Console.WriteLine(" FRUITBANK SANDBOX - SignalR Test Mode"); Console.WriteLine("==========================================="); -Console.WriteLine($" Database: {databaseName}"); Console.WriteLine($" Base URL: http://localhost:59579"); Console.WriteLine($" SignalR Hub: {fruitBankHubEndPoint}"); Console.WriteLine($" Logger Hub: {loggerHubEndPoint}"); diff --git a/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/TestSignalREndpoint.cs b/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/TestSignalREndpoint.cs new file mode 100644 index 0000000..80fea18 --- /dev/null +++ b/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/TestSignalREndpoint.cs @@ -0,0 +1,587 @@ +using AyCode.Services.SignalRs; +using FruitBank.Common.Dtos; +using FruitBank.Common.SignalRs; +using System.Globalization; +using System.Text.Json.Serialization; + +namespace Mango.Sandbox.EndPoints; + +/// +/// Egyszerû teszt SignalR endpoint a DevAdminSignalRHub teszteléséhez. +/// Ez az endpoint minimális függõséggel rendelkezik, hogy könnyebben diagnosztizálható legyen a SignalR Hub mûködése. +/// +public class TestSignalREndpoint : ITestSignalREndpointServer +{ + #region Primitív Paraméter Handlerek + + /// + /// Egyszerû ping metódus - visszaadja a kapott üzenetet és egy timestampet. + /// + [SignalR(TestSignalRTags.PingTag)] + public Task Ping(string message) + { + return Task.FromResult(new TestPingResponse + { + Message = message, + ReceivedAt = DateTime.UtcNow, + ServerInfo = $"Sandbox Server - {Environment.MachineName}" + }); + } + + /// + /// Int paraméter teszt + /// + [SignalR(TestSignalRTags.SingleIntParam)] + public Task HandleSingleInt(int value) + { + return Task.FromResult($"Received: {value}"); + } + + /// + /// Két int paraméter teszt + /// + [SignalR(TestSignalRTags.TwoIntParams)] + public Task HandleTwoInts(int a, int b) + { + return Task.FromResult(a + b); + } + + /// + /// Bool paraméter teszt + /// + [SignalR(TestSignalRTags.BoolParam)] + public Task HandleBool(bool loadRelations) + { + return Task.FromResult(loadRelations); + } + + /// + /// String paraméter teszt + /// + [SignalR(TestSignalRTags.StringParam)] + public Task HandleString(string text) + { + return Task.FromResult($"Echo: {text}"); + } + + /// + /// Guid paraméter teszt + /// + [SignalR(TestSignalRTags.GuidParam)] + public Task HandleGuid(Guid id) + { + return Task.FromResult(id); + } + + /// + /// Enum paraméter teszt + /// + [SignalR(TestSignalRTags.EnumParam)] + public Task HandleEnum(TestStatus status) + { + return Task.FromResult(status); + } + + /// + /// Paraméter nélküli metódus teszt + /// + [SignalR(TestSignalRTags.NoParams)] + public Task HandleNoParams() + { + return Task.FromResult("OK"); + } + + /// + /// Több típusú paraméter teszt + /// + [SignalR(TestSignalRTags.MultipleTypesParams)] + public Task HandleMultipleTypes(bool flag, string text, int number) + { + return Task.FromResult($"{flag}-{text}-{number}"); + } + + /// + /// Decimal paraméter teszt + /// + [SignalR(TestSignalRTags.DecimalParam)] + public Task HandleDecimal(decimal value) + { + return Task.FromResult(value * 2); + } + + /// + /// DateTime paraméter teszt + /// + [SignalR(TestSignalRTags.DateTimeParam)] + public Task HandleDateTime(DateTime dateTime) + { + return Task.FromResult(dateTime); + } + + /// + /// Double paraméter teszt + /// + [SignalR(TestSignalRTags.DoubleParam)] + public Task HandleDouble(double value) + { + return Task.FromResult(value); + } + + /// + /// Long paraméter teszt + /// + [SignalR(TestSignalRTags.LongParam)] + public Task HandleLong(long value) + { + return Task.FromResult(value); + } + + #endregion + + #region Komplex Objektum Handlerek + + /// + /// Egyszerû echo metódus - visszaadja a kapott objektumot változtatás nélkül. + /// + [SignalR(TestSignalRTags.EchoTag)] + public Task Echo(TestEchoRequest request) + { + return Task.FromResult(new TestEchoResponse + { + Id = request?.Id ?? 0, + Name = request?.Name ?? "Unknown", + Timestamp = DateTime.UtcNow, + EchoedSuccessfully = true + }); + } + + /// + /// TestOrderItem komplex objektum teszt + /// + [SignalR(TestSignalRTags.TestOrderItemParam)] + public Task HandleTestOrderItem(TestOrderItem item) + { + return Task.FromResult(new TestOrderItem + { + Id = item.Id, + ProductName = $"Processed: {item.ProductName}", + Quantity = item.Quantity * 2, + UnitPrice = item.UnitPrice * 2, + }); + } + + /// + /// TestOrder komplex objektum teszt (beágyazott objektumokkal) + /// + [SignalR(TestSignalRTags.TestOrderParam)] + public Task HandleTestOrder(TestOrder order) + { + return Task.FromResult(order); + } + + /// + /// SharedTag komplex objektum teszt + /// + [SignalR(TestSignalRTags.SharedTagParam)] + public Task HandleSharedTag(SharedTag tag) + { + return Task.FromResult(tag); + } + + #endregion + + #region Kollekció Handlerek + + /// + /// Lista visszaadása teszthez. + /// + [SignalR(TestSignalRTags.GetTestItems)] + public Task> GetTestItems() + { + var items = new List + { + new() { Id = 1, Name = "Item 1", Value = 100.5m }, + new() { Id = 2, Name = "Item 2", Value = 200.75m }, + new() { Id = 3, Name = "Item 3", Value = 300.25m } + }; + return Task.FromResult(items); + } + + /// + /// Int tömb paraméter teszt + /// + [SignalR(TestSignalRTags.IntArrayParam)] + public Task HandleIntArray(int[] values) + { + return Task.FromResult(values.Select(x => x * 2).ToArray()); + } + + /// + /// Guid tömb paraméter teszt + /// + [SignalR(TestSignalRTags.GuidArrayParam)] + public Task HandleGuidArray(Guid[] ids) + { + return Task.FromResult(ids); + } + + /// + /// String lista paraméter teszt + /// + [SignalR(TestSignalRTags.StringListParam)] + public Task> HandleStringList(List items) + { + return Task.FromResult(items.Select(x => x.ToUpper()).ToList()); + } + + /// + /// TestOrderItem lista paraméter teszt + /// + [SignalR(TestSignalRTags.TestOrderItemListParam)] + public Task> HandleTestOrderItemList(List items) + { + return Task.FromResult(items); + } + + /// + /// Int lista paraméter teszt + /// + [SignalR(TestSignalRTags.IntListParam)] + public Task> HandleIntList(List numbers) + { + return Task.FromResult(numbers.Select(x => x * 2).ToList()); + } + + /// + /// Bool tömb paraméter teszt + /// + [SignalR(TestSignalRTags.BoolArrayParam)] + public Task HandleBoolArray(bool[] flags) + { + return Task.FromResult(flags); + } + + /// + /// Vegyes paraméterek tömbbel teszt + /// + [SignalR(TestSignalRTags.MixedWithArrayParam)] + public Task HandleMixedWithArray(bool flag, int[] numbers, string text) + { + return Task.FromResult($"{flag}-[{string.Join(",", numbers)}]-{text}"); + } + + /// + /// Beágyazott lista teszt + /// + [SignalR(TestSignalRTags.NestedListParam)] + public Task>> HandleNestedList(List> nestedList) + { + return Task.FromResult(nestedList); + } + + /// + /// Long tömb paraméter teszt + /// + [SignalR(TestSignalRTags.LongArrayParam)] + public Task HandleLongArray(long[] values) + { + return Task.FromResult(values); + } + + /// + /// Decimal tömb paraméter teszt + /// + [SignalR(TestSignalRTags.DecimalArrayParam)] + public Task HandleDecimalArray(decimal[] values) + { + return Task.FromResult(values); + } + + /// + /// DateTime tömb paraméter teszt + /// + [SignalR(TestSignalRTags.DateTimeArrayParam)] + public Task HandleDateTimeArray(DateTime[] values) + { + return Task.FromResult(values); + } + + /// + /// Enum tömb paraméter teszt + /// + [SignalR(TestSignalRTags.EnumArrayParam)] + public Task HandleEnumArray(TestStatus[] values) + { + return Task.FromResult(values); + } + + /// + /// Double tömb paraméter teszt + /// + [SignalR(TestSignalRTags.DoubleArrayParam)] + public Task HandleDoubleArray(double[] values) + { + return Task.FromResult(values); + } + + /// + /// SharedTag tömb paraméter teszt + /// + [SignalR(TestSignalRTags.SharedTagArrayParam)] + public Task HandleSharedTagArray(SharedTag[] tags) + { + return Task.FromResult(tags); + } + + /// + /// Dictionary paraméter teszt + /// + [SignalR(TestSignalRTags.DictionaryParam)] + public Task> HandleDictionary(Dictionary dict) + { + return Task.FromResult(dict); + } + + #endregion + + #region Vegyes Paraméter Handlerek + + /// + /// Int és DTO vegyes paraméter teszt + /// + [SignalR(TestSignalRTags.IntAndDtoParam)] + public Task HandleIntAndDto(int id, TestOrderItem item) + { + return Task.FromResult($"{id}-{item?.ProductName}"); + } + + /// + /// DTO és lista vegyes paraméter teszt + /// + [SignalR(TestSignalRTags.DtoAndListParam)] + public Task HandleDtoAndList(TestOrderItem item, List numbers) + { + return Task.FromResult($"{item?.ProductName}-[{string.Join(",", numbers ?? [])}]"); + } + + /// + /// Három komplex paraméter teszt + /// + [SignalR(TestSignalRTags.ThreeComplexParams)] + public Task HandleThreeComplexParams(TestOrderItem item, List tags, SharedTag sharedTag) + { + return Task.FromResult($"{item?.ProductName}-{tags?.Count}-{sharedTag?.Name}"); + } + + /// + /// Öt paraméter teszt + /// + [SignalR(TestSignalRTags.FiveParams)] + public Task HandleFiveParams(int a, string b, bool c, Guid d, decimal e) + { + return Task.FromResult($"{a}-{b}-{c}-{d}-{e.ToString(CultureInfo.InvariantCulture)}"); + } + + #endregion + + #region FruitBank Specifikus Metódusok + + /// + /// OrderDto lista visszaadása ID-k alapján + /// + [SignalR(SignalRTags.GetAllOrderDtoByIds)] + public Task> GetOrderDtoByIds(int[] orderIds) + { + return Task.FromResult(new List()); + } + + #endregion +} + +/// +/// Teszt SignalR Tags - egyszerû értékek a teszteléshez +/// +public static class TestSignalRTags +{ + // Eredeti tagok + public const int PingTag = SignalRTags.PingTag; + public const int EchoTag = SignalRTags.EchoTag; + public const int GetTestItems = 9003; + + // Primitív paraméterek + public const int SingleIntParam = 9010; + public const int TwoIntParams = 9011; + public const int BoolParam = 9012; + public const int StringParam = 9013; + public const int GuidParam = 9014; + public const int EnumParam = 9015; + public const int NoParams = 9016; + public const int MultipleTypesParams = 9017; + public const int DecimalParam = 9018; + public const int DateTimeParam = 9019; + public const int DoubleParam = 9020; + public const int LongParam = 9021; + + // Komplex objektumok + public const int TestOrderItemParam = 9030; + public const int TestOrderParam = 9031; + public const int SharedTagParam = 9032; + + // Kollekciók + public const int IntArrayParam = 9040; + public const int GuidArrayParam = 9041; + public const int StringListParam = 9042; + public const int TestOrderItemListParam = 9043; + public const int IntListParam = 9044; + public const int BoolArrayParam = 9045; + public const int MixedWithArrayParam = 9046; + public const int NestedListParam = 9047; + public const int LongArrayParam = 9048; + public const int DecimalArrayParam = 9049; + public const int DateTimeArrayParam = 9050; + public const int EnumArrayParam = 9051; + public const int DoubleArrayParam = 9052; + public const int SharedTagArrayParam = 9053; + public const int DictionaryParam = 9054; + + // Vegyes paraméterek + public const int IntAndDtoParam = 9060; + public const int DtoAndListParam = 9061; + public const int ThreeComplexParams = 9062; + public const int FiveParams = 9063; +} + +/// +/// Interface a TestSignalREndpoint-hoz +/// +public interface ITestSignalREndpointServer +{ + // Primitívek + Task Ping(string message); + Task HandleSingleInt(int value); + Task HandleTwoInts(int a, int b); + Task HandleBool(bool loadRelations); + Task HandleString(string text); + Task HandleGuid(Guid id); + Task HandleEnum(TestStatus status); + Task HandleNoParams(); + Task HandleMultipleTypes(bool flag, string text, int number); + Task HandleDecimal(decimal value); + Task HandleDateTime(DateTime dateTime); + Task HandleDouble(double value); + Task HandleLong(long value); + + // Komplex objektumok + Task Echo(TestEchoRequest request); + Task HandleTestOrderItem(TestOrderItem item); + Task HandleTestOrder(TestOrder order); + Task HandleSharedTag(SharedTag tag); + + // Kollekciók + Task> GetTestItems(); + Task HandleIntArray(int[] values); + Task HandleGuidArray(Guid[] ids); + Task> HandleStringList(List items); + Task> HandleTestOrderItemList(List items); + Task> HandleIntList(List numbers); + Task HandleBoolArray(bool[] flags); + Task HandleMixedWithArray(bool flag, int[] numbers, string text); + Task>> HandleNestedList(List> nestedList); + Task HandleLongArray(long[] values); + Task HandleDecimalArray(decimal[] values); + Task HandleDateTimeArray(DateTime[] values); + Task HandleEnumArray(TestStatus[] values); + Task HandleDoubleArray(double[] values); + Task HandleSharedTagArray(SharedTag[] tags); + Task> HandleDictionary(Dictionary dict); + + // Vegyes paraméterek + Task HandleIntAndDto(int id, TestOrderItem item); + Task HandleDtoAndList(TestOrderItem item, List numbers); + Task HandleThreeComplexParams(TestOrderItem item, List tags, SharedTag sharedTag); + Task HandleFiveParams(int a, string b, bool c, Guid d, decimal e); +} + +#region DTOs + +public class TestPingResponse +{ + public string Message { get; set; } = string.Empty; + public DateTime ReceivedAt { get; set; } + public string ServerInfo { get; set; } = string.Empty; +} + +public class TestEchoRequest +{ + public int Id { get; set; } + public string Name { get; set; } = string.Empty; +} + +public class TestEchoResponse +{ + public int Id { get; set; } + public string Name { get; set; } = string.Empty; + public DateTime Timestamp { get; set; } + public bool EchoedSuccessfully { get; set; } +} + +public class TestItem +{ + public int Id { get; set; } + public string Name { get; set; } = string.Empty; + public decimal Value { get; set; } +} + +/// +/// Teszt enum a különbözõ állapotok teszteléséhez +/// +public enum TestStatus +{ + Pending = 0, + Active = 1, + Completed = 2, + Cancelled = 3 +} + +/// +/// Teszt rendelési tétel komplex objektum teszteléshez +/// +public class TestOrderItem +{ + public int Id { get; set; } + + public string ProductName { get; set; } = string.Empty; + + public int Quantity { get; set; } + + public decimal UnitPrice { get; set; } + + public decimal TotalPrice => Quantity * UnitPrice; +} + +/// +/// Teszt rendelés beágyazott objektumokkal +/// +public class TestOrder +{ + public int Id { get; set; } + public string CustomerName { get; set; } = string.Empty; + public DateTime OrderDate { get; set; } + public TestStatus Status { get; set; } + public List Items { get; set; } = []; + public decimal TotalAmount => Items.Sum(x => x.TotalPrice); +} + +/// +/// Megosztott tag objektum teszteléshez +/// +public class SharedTag +{ + public int Id { get; set; } + public string Name { get; set; } = string.Empty; + public string? Description { get; set; } + public DateTime CreatedAt { get; set; } + public bool IsActive { get; set; } +} + +#endregion diff --git a/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/appsettings.json b/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/appsettings.json index 0032257..abf9e66 100644 --- a/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/appsettings.json +++ b/Tests/Mango.Sandbox/Mango.Sandbox.EndPoints/appsettings.json @@ -1,13 +1,36 @@ { - "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": "*" + "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" + } + }, + "AyCode": { + "ProjectId": "f9f9383f-c459-4b9f-b0b5-201bd4a9c21b", + "Urls": { + "BaseUrl": "https://localhost:59579", + "ApiBaseUrl": "https://localhost:59579" + }, + "Logger": { + "AppType": "Server", + "LogLevel": "Detail", + "LogWriters": [ + { + "LogLevel": "Detail", + "LogWriterType": "FruitBank.Common.Server.Services.Loggers.ConsoleLogWriter, FruitBank.Common.Server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" + }, + //{ + // "LogLevel": "Detail", + // "LogWriterType": "Mango.Nop.Services.Loggers.NopLogWriter, Mango.Nop.Services, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" + //} + ] + } + }, + "AllowedHosts": "*" + + }