FruitBankHybridApp/FruitBankHybrid.Shared.Tests/ToonTests.cs

309 lines
14 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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()}");
}
}
}
[TestMethod]
public void ToonTypes_NavigationMetadata_ShouldBeComplete()
{
var toon = AcToonSerializer.SerializeTypeMetadata<Shipping>();
Console.WriteLine(toon);
Console.WriteLine("\n=== NAVIGATION METADATA ELLENŐRZÉS ===\n");
var lines = toon.Split('\n').Select(x => x.TrimEnd()).ToList();
// Ismerten egyirányú kapcsolatok - ezeknél nincs inverse property a másik oldalon
// Customer: NopCommerce domain entity, nincs benne Orders kollekció
// OrderNotes: OrderNote osztályban nincs Order navigation property
// ProductDto: nincs benne OrderItems kollekció
// GenericAttributes: polimorf kapcsolat ExpressionPredicate-tel, nincs inverse ÉS nincs egyértelmű FK
// FONTOS: Csak az inverse-property hiányát engedjük! Az other-key-nek léteznie kell!
var knownUnidirectionalNavigations = new HashSet<string>
{
"Customer",
"OrderNotes",
"ProductDto",
"GenericAttributes",
"ShippingDocumentFile",
"Pallet"
};
// GenericAttributes speciális eset - polimorf, nincs other-key sem
var knownPolymorphicNavigations = new HashSet<string>
{
"GenericAttributes"
};
// FK property-k NEM tartalmazhatnak foreign-key attribútumot
for (int i = 0; i < lines.Count; i++)
{
var line = lines[i].Trim();
if (line.EndsWith("Id: int") || line.EndsWith("Id: int?"))
{
int j = i + 1;
while (j < lines.Count)
{
if (lines[j].StartsWith(" ") && !lines[j].StartsWith(" "))
break;
if (lines[j].StartsWith(" "))
{
var metaLine = lines[j].Trim();
if (metaLine.StartsWith("foreign-key:"))
{
Assert.Fail($"FK property nem tartalmazhat foreign-key attribútumot: {line} -> {metaLine}");
}
}
j++;
}
}
}
Console.WriteLine("✓ FK property-k nem tartalmaznak foreign-key attribútumot\n");
// Számoljuk meg a hiányzó navigation metadatokat
var missingMetadata = new List<string>();
var skippedUnidirectional = new List<string>();
for (int i = 0; i < lines.Count; i++)
{
var line = lines[i].Trim();
// Navigation property-k keresése
if (line.Contains(": ") &&
!line.Contains(": int") && !line.Contains(": string") &&
!line.Contains(": DateTime") && !line.Contains(": decimal") &&
!line.Contains(": bool") && !line.Contains(": Guid") &&
!line.Contains(": double") && !line.Contains(": float") &&
!line.Contains("description:") && !line.Contains("purpose:") &&
!line.Contains("navigation:") && !line.Contains("foreign-key:") &&
!line.Contains("table-name:") && !line.Contains("constraints:") &&
!line.Contains("inverse-property:") && !line.Contains("other-key:") &&
!line.Contains("primary-key:") && !line.Contains("examples:") &&
!line.Contains("@meta") && !line.Contains("@types") &&
!line.Contains("version") && !line.Contains("format") && !line.Contains("source-code-language") &&
!line.Contains("underlying-type:") && !line.Contains("default-value:") && !line.Contains("values:"))
{
var propName = line.Split(':')[0].Trim();
if (string.IsNullOrEmpty(propName) || propName == "types") continue;
// Következő sorok metadatainak összegyűjtése
var metadata = new HashSet<string>();
int j = i + 1;
while (j < lines.Count && lines[j].StartsWith(" ") && lines[j].Trim().Contains(':'))
{
var metaLine = lines[j].Trim();
if (metaLine.StartsWith("navigation:")) metadata.Add("navigation");
if (metaLine.StartsWith("foreign-key:")) metadata.Add("foreign-key");
if (metaLine.StartsWith("inverse-property:")) metadata.Add("inverse-property");
if (metaLine.StartsWith("other-key:")) metadata.Add("other-key");
j++;
}
// Ha van navigation attribútum, ellenőrizzük a szükséges metadatokat
if (metadata.Contains("navigation"))
{
var navLine = lines.Skip(i + 1).FirstOrDefault(x => x.Trim().StartsWith("navigation:"));
if (navLine != null)
{
var isUnidirectional = knownUnidirectionalNavigations.Contains(propName);
var isPolymorphic = knownPolymorphicNavigations.Contains(propName);
if (navLine.Contains("many-to-one"))
{
if (!metadata.Contains("foreign-key"))
missingMetadata.Add($"{propName} (ManyToOne): hiányzik foreign-key");
if (!metadata.Contains("inverse-property"))
{
if (isUnidirectional)
skippedUnidirectional.Add($"{propName} (ManyToOne): egyirányú kapcsolat, nincs inverse");
else
missingMetadata.Add($"{propName} (ManyToOne): hiányzik inverse-property");
}
}
else if (navLine.Contains("one-to-many"))
{
// other-key: polimorf kapcsolatoknál nem kötelező
if (!metadata.Contains("other-key"))
{
if (isPolymorphic)
{
skippedUnidirectional.Add($"{propName} (OneToMany): polimorf kapcsolat, nincs other-key");
}
else
{
// DEBUG: részletes info
Console.WriteLine($"\n[DEBUG] {propName} (OneToMany) - other-key hiányzik!");
// Keressük meg a property típusát a Toon outputban
var propTypePart = line.Split(':').LastOrDefault()?.Trim() ?? "";
Console.WriteLine($" Property type: {propTypePart}");
// Ha List<X> formátum, keressük meg X-et
if (propTypePart.StartsWith("List<") && propTypePart.EndsWith(">"))
{
var elementTypeName = propTypePart.Substring(5, propTypePart.Length - 6);
Console.WriteLine($" Element type: {elementTypeName}");
// Keressük meg az element type definícióját
var elementTypeDefIndex = lines.FindIndex(l => l.Trim().StartsWith($"{elementTypeName}:"));
if (elementTypeDefIndex >= 0)
{
Console.WriteLine($" Element type definition found at line {elementTypeDefIndex}");
// Listázzuk ki az element type property-jeit amik "Id"-re végződnek
for (int k = elementTypeDefIndex + 1; k < lines.Count; k++)
{
var propLine = lines[k];
if (!propLine.StartsWith(" ")) break; // Új típus definíció
if (propLine.StartsWith(" ")) continue; // Metaadat, skip
var trimmed = propLine.Trim();
if (trimmed.EndsWith(": int") && trimmed.Contains("Id"))
{
Console.WriteLine($" FK candidate: {trimmed}");
}
}
}
}
missingMetadata.Add($"{propName} (OneToMany): hiányzik other-key");
}
}
if (!metadata.Contains("inverse-property"))
{
if (isUnidirectional)
skippedUnidirectional.Add($"{propName} (OneToMany): egyirányú kapcsolat, nincs inverse");
else
missingMetadata.Add($"{propName} (OneToMany): hiányzik inverse-property");
}
}
}
}
}
}
if (skippedUnidirectional.Count > 0)
{
Console.WriteLine("EGYIRÁNYÚ/POLIMORF KAPCSOLATOK (nem hiba):");
foreach (var skipped in skippedUnidirectional)
{
Console.WriteLine($" {skipped}");
}
Console.WriteLine();
}
if (missingMetadata.Count > 0)
{
Console.WriteLine("HIÁNYZÓ METAADATOK:");
foreach (var missing in missingMetadata)
{
Console.WriteLine($" - {missing}");
}
Assert.Fail($"Hiányzó navigation metaadatok: {missingMetadata.Count} db");
}
Console.WriteLine("✓ Minden navigation property tartalmazza a szükséges metadatokat");
}
}