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.GetResponseData>(); 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.GetResponseData(); 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.GetResponseData(); 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.GetResponseData(); 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.GetResponseData(); 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 #region Binary Serialization Tesztek - AcBinaryDeserializationException reprodukálása /// /// Reprodukálja a GetMeasuringUsers hibát: AcBinaryDeserializationException: Invalid interned string index /// A hiba akkor jelentkezik, amikor a szerver Binary formátumban küldi a választ (List), /// de a kliens deszerializálásnál az interned string index hibás. /// [TestMethod] public async Task GetAllAsync_CustomerDtoList_BinaryDeserialization_ThrowsInternedStringIndexError() { // Act - GetAllAsync>(tag) // Ez a hívás a GetMeasuringUsers-höz hasonló forgatókönyvet reprodukál var result = await _client.GetAllAsync>(TestSignalRTags.GetCustomerDtoList); // Assert Assert.IsNotNull(result); Assert.IsTrue(result.Count > 0, "Should return at least one CustomerDto"); // Ellenőrizzük, hogy minden CustomerDto megfelelően deszerializálódott foreach (var dto in result) { Assert.IsTrue(dto.Id > 0, $"CustomerDto.Id should be > 0, got {dto.Id}"); Assert.IsFalse(string.IsNullOrEmpty(dto.Username), "CustomerDto.Username should not be empty"); Assert.IsFalse(string.IsNullOrEmpty(dto.Email), "CustomerDto.Email should not be empty"); Console.WriteLine($"[GetAllAsync_CustomerDtoList] Id={dto.Id}, Username={dto.Username}, Email={dto.Email}, FullName={dto.FullName}"); } } /// /// Nagyobb CustomerDto lista tesztelése - több interned string a szerializációban /// [TestMethod] public async Task GetAllAsync_LargeCustomerDtoList_BinaryDeserialization_Success() { // Act var result = await _client.GetAllAsync>(TestSignalRTags.GetLargeCustomerDtoList); // Assert Assert.IsNotNull(result); Assert.IsTrue(result.Count >= 10, $"Should return at least 10 CustomerDtos, got {result.Count}"); Console.WriteLine($"[GetAllAsync_LargeCustomerDtoList] Received {result.Count} items"); } #endregion }