|
| 1 | +using System.Text.RegularExpressions; |
| 2 | +using XafLogicExplainer.Core.Generators; |
| 3 | + |
| 4 | +namespace XafLogicExplainer.Tests; |
| 5 | + |
| 6 | +/// <summary> |
| 7 | +/// What a summary of fixed width names once an entity carries its base's columns. |
| 8 | +/// </summary> |
| 9 | +/// <remarks> |
| 10 | +/// Folding inherited properties (<see cref="InheritedPropertyFoldTests"/>) gives every entity the |
| 11 | +/// columns it persists, in the order the class reads them — root down. Two summaries then take the |
| 12 | +/// first few of that list, and on an application with a shared audit base the first few are the |
| 13 | +/// base's for every entity at once: the tables that exist to tell entities apart end up naming the |
| 14 | +/// same columns in every row, and none of the ones that differ. |
| 15 | +/// <para> |
| 16 | +/// The full listings are unaffected and still read root down. This is only about the summaries, |
| 17 | +/// where the width is the whole constraint. |
| 18 | +/// </para> |
| 19 | +/// </remarks> |
| 20 | +public class InheritedPropertySummaryTests |
| 21 | +{ |
| 22 | + private static string Index => |
| 23 | + new AgentContextGenerator("0.9.0").GenerateIndex(SampleProjects.AuditedXpo, []); |
| 24 | + |
| 25 | + [Fact] |
| 26 | + public void AnEntitysOwnColumnsSurviveAFixedWidthSummary() |
| 27 | + { |
| 28 | + // Receipt declares two columns and inherits six. Ranked by nothing but position, the six |
| 29 | + // fill all five slots and the reader learns that a receipt has a CreatedBy. |
| 30 | + Assert.Equal(["Reference", "Amount", "CreatedBy", "CreatedOn", "ChangedBy"], Notable("Receipt")); |
| 31 | + } |
| 32 | + |
| 33 | + [Fact] |
| 34 | + public void RequiredColumnsStillOutrankTheRestOfTheEntitysOwn() |
| 35 | + { |
| 36 | + // Own-before-inherited is the outer sort; the existing ranking still orders each group. |
| 37 | + Assert.Equal(["Number", "IssuedOn", "Total", "CreatedBy", "CreatedOn"], Notable("Invoice")); |
| 38 | + } |
| 39 | + |
| 40 | + [Fact] |
| 41 | + public void TheBaseItselfStillNamesItsOwnColumns() |
| 42 | + { |
| 43 | + // The base declares all six, so the rule must not be "hide inherited" -- it is "declare |
| 44 | + // first". A base whose row went blank would be the same defect facing the other way. |
| 45 | + Assert.Equal(["CreatedBy", "CreatedOn", "ChangedBy", "ChangedOn", "RowVersion"], Notable("AuditedObject")); |
| 46 | + } |
| 47 | + |
| 48 | + [Fact] |
| 49 | + public void TheNavigationSummaryNamesTheEntitysOwnColumnsFirstToo() |
| 50 | + { |
| 51 | + // The same eight-slot summary, in the documents published to a Copilot rather than to a |
| 52 | + // coding agent -- one fix per reader, or the reader who gets missed keeps the defect. |
| 53 | + // Generated in the default language, which is Spanish; the ordering is not translated. |
| 54 | + var sections = new MarkdownDocumentationGenerator().GenerateSections(SampleProjects.AuditedXpo); |
| 55 | + var navigation = sections.Single(section => section.Content.Contains("#### Receipt")); |
| 56 | + |
| 57 | + var line = navigation.Content |
| 58 | + .Split('\n') |
| 59 | + .SkipWhile(text => !text.StartsWith("#### Receipt", StringComparison.Ordinal)) |
| 60 | + .First(text => text.Contains("Propiedades principales", StringComparison.Ordinal)); |
| 61 | + |
| 62 | + Assert.StartsWith( |
| 63 | + "- **Propiedades principales:** Reference, Amount, CreatedBy", |
| 64 | + line.Trim(), |
| 65 | + StringComparison.Ordinal); |
| 66 | + } |
| 67 | + |
| 68 | + /// <summary>The property names in one row of the agent context's entity table.</summary> |
| 69 | + private static List<string> Notable(string className) |
| 70 | + { |
| 71 | + var row = Index |
| 72 | + .Split('\n') |
| 73 | + .Single(line => line.StartsWith($"| **{className}** ", StringComparison.Ordinal)); |
| 74 | + |
| 75 | + return [.. Regex.Matches(row.Split('|')[3], "`([^`]+)`").Select(match => match.Groups[1].Value)]; |
| 76 | + } |
| 77 | +} |
0 commit comments