From 6dea39c5772bcec5b5d960ab2c99bd8def1b7432 Mon Sep 17 00:00:00 2001 From: Jan Ulrichts Date: Thu, 6 Aug 2026 13:59:42 +0200 Subject: [PATCH 1/5] Fixed workflow to cover all supported .NET versions for building and testing. --- .github/workflows/build-and-test.yml | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index 412f9b2..624c317 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -16,24 +16,23 @@ on: jobs: build-and-test: runs-on: ubuntu-latest - steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v7 - name: Setup .NET - uses: actions/setup-dotnet@v4 + uses: actions/setup-dotnet@v6 with: - dotnet-version: 9.0.x + dotnet-version: | + 8.0.x + 9.0.x + 10.0.x - name: Check formatter rules run: dotnet format --verify-no-changes --verbosity diagnostic - - name: Restore dependencies - run: dotnet restore - - name: Build - run: dotnet build --no-restore + run: dotnet build - name: Test run: dotnet test --no-build --verbosity normal From c3d7adb9e3b2caf6c9be3ab6f26745bba7890f2a Mon Sep 17 00:00:00 2001 From: Jan Ulrichts Date: Thu, 6 Aug 2026 14:02:57 +0200 Subject: [PATCH 2/5] Tweaked error messages when source and destination nodes aren't found when adding a link. Added tests to validate links that contain deeply nested nodes. --- .../FlowchartTests.cs | 80 ++++++++++++++++++- 1 file changed, 78 insertions(+), 2 deletions(-) diff --git a/tests/Mermaid.Flowcharts.Tests/FlowchartTests.cs b/tests/Mermaid.Flowcharts.Tests/FlowchartTests.cs index dc9c9d7..025c292 100644 --- a/tests/Mermaid.Flowcharts.Tests/FlowchartTests.cs +++ b/tests/Mermaid.Flowcharts.Tests/FlowchartTests.cs @@ -123,7 +123,7 @@ public void Flowchart_WhenLinkSourceNotPresent_AddLinkShouldThrow() InvalidOperationException exception = Assert.Throws( () => flowchart.AddLink(link) ); - Assert.Contains("Cannot add link to flowchart: the source and the destination nodes should both be present within the flowchart.", exception.Message); + Assert.Contains("Cannot add link to flowchart: the source node should be present within the flowchart.", exception.Message); } [Fact] @@ -140,7 +140,7 @@ public void Flowchart_WhenLinkDestinationNotPresent_AddLinkShouldThrow() InvalidOperationException exception = Assert.Throws( () => flowchart.AddLink(link) ); - Assert.Contains("Cannot add link to flowchart: the source and the destination nodes should both be present within the flowchart.", exception.Message); + Assert.Contains("Cannot add link to flowchart: the destination node should be present within the flowchart.", exception.Message); } [Fact] @@ -805,4 +805,80 @@ subgraph ssg ["Subsubgraph"] // Assert Assert.Equal(expected, actual); } + + [Fact] + public void Flowchart_ShouldLinkToNodeThreeSubgraphLevelsDeep() + { + Flowchart flowchart = new(); + Node top = Node.Create("top", "Top"); + Subgraph outer = Subgraph.Create("outer", "Outer"); + Subgraph middle = Subgraph.Create("middle", "Middle"); + Subgraph inner = Subgraph.Create("inner", "Inner"); + Node deep = Node.Create("deep", "Deep"); + + inner.AddNode(deep); + middle.AddNode(inner); + outer.AddNode(middle); + flowchart.AddNode(top).AddNode(outer); + flowchart.AddLink(Link.Create(top, deep)); + + string expected = + """ + flowchart TD + top["Top"] + + subgraph outer ["Outer"] + + subgraph middle ["Middle"] + + subgraph inner ["Inner"] + deep["Deep"] + end + end + end + + top ---> deep + + """; + + Assert.Equal(expected, flowchart.ToMermaidString(0, " ")); + } + + [Fact] + public void Subgraph_ShouldLinkToNodeNestedInsideInnerSubgraph() + { + Flowchart flowchart = new(); + Node a = Node.Create("a", "A"); + Subgraph outer = Subgraph.Create("outer", "Outer"); + Subgraph middle = Subgraph.Create("middle", "Middle"); + Subgraph inner = Subgraph.Create("inner", "Inner"); + Node deep = Node.Create("deep", "Deep"); + + inner.AddNode(deep); + middle.AddNode(inner); + outer.AddNode(a).AddNode(middle); + flowchart.AddNode(outer); + outer.AddLink(Link.Create(a, deep)); + + string expected = + """ + flowchart TD + + subgraph outer ["Outer"] + a["A"] + + subgraph middle ["Middle"] + + subgraph inner ["Inner"] + deep["Deep"] + end + end + + a ---> deep + end + + """; + + Assert.Equal(expected, flowchart.ToMermaidString(0, " ")); + } } From a84673343c15f4f01c082bb72021c84a0c08d1e5 Mon Sep 17 00:00:00 2001 From: Jan Ulrichts Date: Thu, 6 Aug 2026 14:04:13 +0200 Subject: [PATCH 3/5] Use distinct exception messages for when a source or a destination node is not found. --- src/Mermaid.Flowcharts/Flowchart.cs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/Mermaid.Flowcharts/Flowchart.cs b/src/Mermaid.Flowcharts/Flowchart.cs index 6859daa..6125b51 100644 --- a/src/Mermaid.Flowcharts/Flowchart.cs +++ b/src/Mermaid.Flowcharts/Flowchart.cs @@ -42,12 +42,18 @@ public Flowchart AddNode(INode node) public Flowchart AddLink(Link link) { - if (AllNodeChildren.Any(link.Source.Equals) && AllNodeChildren.Any(link.Destination.Equals)) + if (!AllNodeChildren.Any(link.Source.Equals)) { - _links.Add(link); - return this; + throw new InvalidOperationException("Cannot add link to flowchart: the source node should be present within the flowchart."); } - throw new InvalidOperationException("Cannot add link to flowchart: the source and the destination nodes should both be present within the flowchart."); + + if (!AllNodeChildren.Any(link.Destination.Equals)) + { + throw new InvalidOperationException("Cannot add link to flowchart: the destination node should be present within the flowchart."); + } + + _links.Add(link); + return this; } public override string ToString() From 614956f8cdefa6279d77aed2d47fc34fed831377 Mon Sep 17 00:00:00 2001 From: Jan Ulrichts Date: Thu, 6 Aug 2026 14:04:30 +0200 Subject: [PATCH 4/5] Fixed deeply nested descendant nodes not being found. --- src/Mermaid.Flowcharts/Subgraphs/Subgraph.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Mermaid.Flowcharts/Subgraphs/Subgraph.cs b/src/Mermaid.Flowcharts/Subgraphs/Subgraph.cs index 61036b8..114a45c 100644 --- a/src/Mermaid.Flowcharts/Subgraphs/Subgraph.cs +++ b/src/Mermaid.Flowcharts/Subgraphs/Subgraph.cs @@ -16,7 +16,7 @@ public record Subgraph : INode public IEnumerable Nodes => _nodes.OfType(); public IEnumerable Subgraphs => _nodes.OfType(); public IEnumerable Links => _links.AsReadOnly(); - public IEnumerable AllNodeChildren => _nodes.Concat(Subgraphs.SelectMany(subgraph => subgraph._nodes)); + public IEnumerable AllNodeChildren => _nodes.Concat(Subgraphs.SelectMany(subgraph => subgraph.AllNodeChildren)); public IEnumerable AllNodes => Nodes.Concat(Subgraphs.SelectMany(subgraph => subgraph.AllNodes)); public IEnumerable AllLinks => Links.Concat(Subgraphs.SelectMany(subgraph => subgraph.AllLinks)); From cbecbd9687f344fd41c658730d083b1ded3eaefa Mon Sep 17 00:00:00 2001 From: Jan Ulrichts Date: Thu, 6 Aug 2026 14:07:11 +0200 Subject: [PATCH 5/5] Ran formatter. --- src/Mermaid.Flowcharts/Flowchart.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Mermaid.Flowcharts/Flowchart.cs b/src/Mermaid.Flowcharts/Flowchart.cs index 6125b51..7f654eb 100644 --- a/src/Mermaid.Flowcharts/Flowchart.cs +++ b/src/Mermaid.Flowcharts/Flowchart.cs @@ -51,7 +51,7 @@ public Flowchart AddLink(Link link) { throw new InvalidOperationException("Cannot add link to flowchart: the destination node should be present within the flowchart."); } - + _links.Add(link); return this; }