Improve AcToonSerializer type metadata handling & tests

- Refined type metadata serialization: collections and dictionaries are now detected and described more accurately, avoiding generic type names (e.g., List`1) and redundant "object" element types.
- Added circular reference protection to type name generation to prevent stack overflows and duplicate type names.
- Updated AcToonSerializerOptions.Compact to use indentation for better readability.
- Introduced ToonTests with unit tests to ensure type metadata correctness, uniqueness, and clarity.
- Added AyCode.Core project to the solution and adjusted namespaces/usings for consistency.
This commit is contained in:
Loretta 2026-01-12 08:36:23 +01:00
parent 38f268ec1d
commit 6d689d3632
3 changed files with 111 additions and 0 deletions

View File

@ -12,6 +12,7 @@ using Nop.Core.Domain.Orders;
using Nop.Core.Domain.Payments;
using System.Linq.Expressions;
using System.Runtime.Serialization;
using AyCode.Core.Serializers.Toons;
namespace FruitBankHybrid.Shared.Tests;

View File

@ -0,0 +1,104 @@
using AyCode.Core.Enums;
using AyCode.Core.Extensions;
using AyCode.Core.Loggers;
using FruitBank.Common;
using FruitBank.Common.Dtos;
using FruitBank.Common.Entities;
using FruitBank.Common.Loggers;
using FruitBankHybrid.Shared.Services.SignalRs;
using Newtonsoft.Json;
using Nop.Core.Domain.Common;
using Nop.Core.Domain.Orders;
using Nop.Core.Domain.Payments;
using System.Linq.Expressions;
using System.Runtime.Serialization;
using AyCode.Core.Serializers.Toons;
namespace FruitBankHybrid.Shared.Tests;
[TestClass]
public sealed class ToonTests
{
private const int CustomerIdAasdDsserverCom = 6; //aasd@dsserver.com
private FruitBankSignalRClient _signalRClient = null!;
[TestInitialize]
public void TestInit()
{
if (!FruitBankConstClient.BaseUrl.Contains("localhost:")) throw new Exception("NEM LOCALHOST-ON TESZTELÜNK!");
_signalRClient = new FruitBankSignalRClient(new List<IAcLogWriterClientBase>
{
//new ConsoleLogWriter(AppType.TestUnit, LogLevel.Detail, nameof(FruitBankClientTests)),
new SignaRClientLogItemWriter(AppType.TestUnit, LogLevel.Detail, nameof(FruitBankClientTests))
});
}
[TestMethod]
public void OrderDtoToToon()
{
var toon = AcToonSerializer.SerializeTypeMetadata<OrderDto>();
Console.WriteLine(toon);
Assert.IsNotEmpty(toon);
}
[TestMethod]
public void ToonTypes_ShouldNotContainList1OrGenericTypeNames()
{
var toon = AcToonSerializer.SerializeTypeMetadata<OrderDto>();
StringAssert.DoesNotMatch(toon, new System.Text.RegularExpressions.Regex(@"List`?1"), "A @meta.types vagy @types szekcióban nem szerepelhet List`1 vagy generikus típusnév.");
}
[TestMethod]
public void ToonTypes_ShouldNotContainDuplicateTypeNames()
{
var toon = AcToonSerializer.SerializeTypeMetadata<OrderDto>();
var typesLine = toon.Split('\n').FirstOrDefault(x => x.TrimStart().StartsWith("types = ["));
Assert.IsNotNull(typesLine, "Nem található types lista a @meta szekcióban.");
var typeNames = typesLine.Substring(typesLine.IndexOf('[') + 1, typesLine.LastIndexOf(']') - typesLine.IndexOf('[') - 1)
.Split(',').Select(x => x.Trim(' ', '"')).Where(x => !string.IsNullOrWhiteSpace(x)).ToList();
var duplicates = typeNames.GroupBy(x => x).Where(g => g.Count() > 1).Select(g => g.Key).ToList();
Assert.IsTrue(duplicates.Count == 0, $"A types listában duplikált típusnév található: {string.Join(", ", duplicates)}");
}
[TestMethod]
public void ToonTypes_EachTypeShouldBeDefinedOnceInTypesSection()
{
var toon = AcToonSerializer.SerializeTypeMetadata<OrderDto>();
var typeDefLines = toon.Split('\n').Where(x => x.TrimEnd().EndsWith(": \"Object of type") || x.TrimEnd().EndsWith(": enum") || x.TrimEnd().EndsWith(": \"Object of type "));
var typeNames = typeDefLines.Select(x => x.Trim().Split(':')[0]).ToList();
var duplicates = typeNames.GroupBy(x => x).Where(g => g.Count() > 1).Select(g => g.Key).ToList();
Assert.IsTrue(duplicates.Count == 0, $"A @types szekcióban duplikált típusdefiníció található: {string.Join(", ", duplicates)}");
}
[TestMethod]
public void ToonTypes_PropertyTypesShouldNotReferenceList1()
{
var toon = AcToonSerializer.SerializeTypeMetadata<OrderDto>();
var lines = toon.Split('\n');
foreach (var line in lines)
{
if (line.Trim().EndsWith(": List`1"))
{
Assert.Fail($"Property List`1 típusra hivatkozik: {line.Trim()}");
}
}
}
[TestMethod]
public void ToonTypes_PropertyDescriptions_ShouldNotBeRedundantOrMisleading()
{
var toon = AcToonSerializer.SerializeTypeMetadata<OrderDto>();
var lines = toon.Split('\n');
foreach (var line in lines)
{
if (line.Trim().StartsWith("description:") && line.Contains("Collection of Object for"))
{
Assert.Fail($"Redundáns vagy félrevezető description: {line.Trim()}");
}
}
}
}

View File

@ -37,6 +37,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AyCode.Blazor.Components.Tests", "..\..\..\Aycode\Source\AyCode.Blazor\AyCode.Blazor.Components.Tests\AyCode.Blazor.Components.Tests.csproj", "{5EFD44C6-DC9E-FEB8-F229-3E07C2E224FA}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AyCode.Core", "..\..\..\Aycode\Source\AyCode.Core\AyCode.Core\AyCode.Core.csproj", "{EC0E3D9A-40DE-52EB-9E66-CFFBB36B5326}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -101,6 +103,10 @@ Global
{5EFD44C6-DC9E-FEB8-F229-3E07C2E224FA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5EFD44C6-DC9E-FEB8-F229-3E07C2E224FA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5EFD44C6-DC9E-FEB8-F229-3E07C2E224FA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EC0E3D9A-40DE-52EB-9E66-CFFBB36B5326}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EC0E3D9A-40DE-52EB-9E66-CFFBB36B5326}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EC0E3D9A-40DE-52EB-9E66-CFFBB36B5326}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EC0E3D9A-40DE-52EB-9E66-CFFBB36B5326}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE