diff --git a/README.md b/README.md
index 612220a..2b4a5ae 100644
--- a/README.md
+++ b/README.md
@@ -87,8 +87,7 @@ dotnet run --project src/ProjGraph.Mcp
projgraph visualize ./MySolution.sln
# Mermaid format for documentation
-projgraph visualize ./MySolution.slnx --format mermaid > docs/dependencies.mmd
-```
+projgraph visualize ./MySolution.slnx --format mermaid > docs/dependencies.mmd```
### Generate Database Diagrams
diff --git a/samples/visualize/simple-dependencies/README.md b/samples/visualize/simple-dependencies/README.md
index f82fe38..ce99a20 100644
--- a/samples/visualize/simple-dependencies/README.md
+++ b/samples/visualize/simple-dependencies/README.md
@@ -14,7 +14,7 @@ projgraph visualize A/A.csproj
**Output:**
-```
+```bash
Projects
├── 📦 A
│ └── → B
diff --git a/specs/001-cli-graph-rendering/spec.md b/specs/001-cli-graph-rendering/spec.md
index 496b521..db049fe 100644
--- a/specs/001-cli-graph-rendering/spec.md
+++ b/specs/001-cli-graph-rendering/spec.md
@@ -78,6 +78,7 @@ As a modern .NET developer, I want the tool to support the new XML-based `.slnx`
- **Description**: Analyzes a .NET solution or project file and returns the dependency graph as a set of nodes and edges.
- **Parameters**:
- `path`: (string) The absolute path to the .sln, .slnx, or .csproj file.
+ - `show_title`: (boolean, optional) Whether to include the title in the diagram (default: true).
- `includePackages`: (boolean) (Out of scope for initial version) Whether to include NuGet package dependencies in the graph.
## Success Criteria *(mandatory)*
diff --git a/specs/002-dbcontext-erd/spec.md b/specs/002-dbcontext-erd/spec.md
index ffb803b..e52e67c 100644
--- a/specs/002-dbcontext-erd/spec.md
+++ b/specs/002-dbcontext-erd/spec.md
@@ -82,6 +82,7 @@ As an AI Assistant, I want to retrieve a Mermaid ERD of the project's data model
- **Parameters**:
- `path`: (string) Absolute path to the DbContext .cs file.
- `contextName`: (string, optional) Specific DbContext class name to use if multiple are present.
+ - `show_title`: (boolean, optional) Whether to include the title in the diagram (default: true).
## Success Criteria *(mandatory)*
diff --git a/specs/003-mermaid-class-diagram/spec.md b/specs/003-mermaid-class-diagram/spec.md
index 5d8242c..3619e13 100644
--- a/specs/003-mermaid-class-diagram/spec.md
+++ b/specs/003-mermaid-class-diagram/spec.md
@@ -96,3 +96,4 @@ As a developer, I want to control the depth of the discovery so the diagram does
- `includeInheritance`: (boolean) Whether to search the workspace for base classes and interfaces.
- `includeDependencies`: (boolean) Whether to search for and include classes used by the target types.
- `depth`: (integer) How many levels of relationships to follow (default: 1).
+ - `show_title`: (boolean, optional) Whether to include the title in the diagram (default: true).
diff --git a/src/ProjGraph.Cli/Commands/ClassDiagramCommand.cs b/src/ProjGraph.Cli/Commands/ClassDiagramCommand.cs
index 3a8b926..0061c7e 100644
--- a/src/ProjGraph.Cli/Commands/ClassDiagramCommand.cs
+++ b/src/ProjGraph.Cli/Commands/ClassDiagramCommand.cs
@@ -59,6 +59,14 @@ public sealed class Settings : CommandSettings
[DefaultValue(1)]
public int Depth { get; init; }
+ ///
+ /// Gets or sets a value indicating whether to include the title in the rendered output.
+ ///
+ [CommandOption("--show-title ")]
+ [Description("Include the diagram title (default true)")]
+ [DefaultValue(true)]
+ public bool ShowTitle { get; init; } = true;
+
///
/// Validates the settings provided by the user.
/// Ensures the file path is valid, exists, and points to a .cs file.
@@ -108,8 +116,8 @@ public override async Task ExecuteAsync(
settings.IncludeDependencies,
settings.Depth);
- var mermaid = mermaidRenderer.Render(model);
- console.WriteLine(mermaid);
+ var mermaidOutput = mermaidRenderer.Render(model, new DiagramOptions(settings.ShowTitle));
+ console.WriteLine(mermaidOutput);
return 0;
}
diff --git a/src/ProjGraph.Cli/Commands/ErdCommand.cs b/src/ProjGraph.Cli/Commands/ErdCommand.cs
index 29871df..5f73bd0 100644
--- a/src/ProjGraph.Cli/Commands/ErdCommand.cs
+++ b/src/ProjGraph.Cli/Commands/ErdCommand.cs
@@ -49,6 +49,14 @@ public sealed class Settings : CommandSettings
[Description("The name of the DbContext or ModelSnapshot to analyze (optional)")]
public string? ContextName { get; init; }
+ ///
+ /// Gets or sets a value indicating whether to include the title in the rendered output.
+ ///
+ [CommandOption("--show-title ")]
+ [Description("Include the diagram title (default true)")]
+ [DefaultValue(true)]
+ public bool ShowTitle { get; init; } = true;
+
///
/// Validates the settings provided for the command.
/// Ensures that the specified path exists, is a .cs file, or is left empty to search the current directory.
@@ -107,8 +115,8 @@ public override async Task ExecuteAsync(
var model = await AnalyzeModelAsync(targetPath, settings.ContextName, cancellationToken);
- var mermaid = mermaidRenderer.Render(model);
- console.WriteLine(mermaid);
+ var mermaidOutput = mermaidRenderer.Render(model, new DiagramOptions(settings.ShowTitle));
+ console.WriteLine(mermaidOutput);
return 0;
}
diff --git a/src/ProjGraph.Cli/Commands/VisualizeCommand.cs b/src/ProjGraph.Cli/Commands/VisualizeCommand.cs
index 1e33342..5a4e0b1 100644
--- a/src/ProjGraph.Cli/Commands/VisualizeCommand.cs
+++ b/src/ProjGraph.Cli/Commands/VisualizeCommand.cs
@@ -24,6 +24,10 @@ public sealed class VisualizeCommand(
IOutputConsole console)
: AsyncCommand
{
+ private const string FormatMermaid = "mermaid";
+ private const string FormatTree = "tree";
+ private const string FormatFlat = "flat";
+
///
/// Represents the settings for the `VisualizeCommand`.
///
@@ -49,6 +53,14 @@ public sealed class Settings : CommandSettings
[DefaultValue("mermaid")]
public string Format { get; private set; } = "mermaid";
+ ///
+ /// Gets or sets a value indicating whether to include the title in the rendered output.
+ ///
+ [CommandOption("--show-title ")]
+ [Description("Include the diagram title (default true)")]
+ [DefaultValue(true)]
+ public bool ShowTitle { get; init; } = true;
+
///
/// Validates the settings provided for the command.
/// Ensures that the specified path exists, is valid, and that the format is "flat", "tree" or "mermaid".
@@ -69,7 +81,7 @@ public override ValidationResult Validate()
}
Format = Format.ToLowerInvariant();
- if (Format != "flat" && Format != "tree" && Format != "mermaid")
+ if (Format != FormatFlat && Format != FormatTree && Format != FormatMermaid)
{
return ValidationResult.Error("Format must be 'flat', 'tree' or 'mermaid'");
}
@@ -101,13 +113,13 @@ public override async Task ExecuteAsync(
{
try
{
- if (settings.Format.Equals("mermaid", StringComparison.OrdinalIgnoreCase))
+ if (settings.Format.Equals(FormatMermaid, StringComparison.OrdinalIgnoreCase))
{
// For mermaid, we want clean stdout, so all status goes to stderr
console.WriteInfo($"Analyzing {settings.Path}...");
var graph = await Task.Run(() => graphService.BuildGraph(settings.Path), cancellationToken);
- console.WriteLine(GetRenderer(settings.Format).Render(graph));
+ console.WriteLine(GetRenderer(settings.Format).Render(graph, new DiagramOptions(settings.ShowTitle)));
}
else
{
@@ -126,7 +138,7 @@ await AnsiConsole.Status()
return 0;
}
- console.WriteLine(GetRenderer(settings.Format).Render(graph));
+ console.WriteLine(GetRenderer(settings.Format).Render(graph, new DiagramOptions(settings.ShowTitle)));
}
return 0;
@@ -152,9 +164,9 @@ private IDiagramRenderer GetRenderer(string format)
{
return format.ToLowerInvariant() switch
{
- "mermaid" => renderers.OfType().First(),
- "tree" => renderers.OfType().First(),
- "flat" => renderers.OfType().First(),
+ FormatMermaid => renderers.OfType().First(),
+ FormatTree => renderers.OfType().First(),
+ FormatFlat => renderers.OfType().First(),
_ => throw new ArgumentException($"Unsupported format: {format}")
};
}
diff --git a/src/ProjGraph.Cli/README.md b/src/ProjGraph.Cli/README.md
index 5d1ae93..4dd94ba 100644
--- a/src/ProjGraph.Cli/README.md
+++ b/src/ProjGraph.Cli/README.md
@@ -21,8 +21,17 @@ projgraph visualize ./MySolution.sln
# Mermaid diagram
projgraph visualize ./MySolution.slnx --format mermaid > graph.mmd
+
+# Mermaid diagram without title header
+projgraph visualize ./MySolution.slnx --format mermaid --show-title false
```
+**Settings**:
+
+- ``: Path to `.sln`, `.slnx`, or `.csproj` file.
+- `-f|--format`: Output format (`flat`, `tree`, `mermaid`). Default: `mermaid`.
+- `--show-title `: Include diagram title. Default: `true`.
+
**Supports**: `.sln`, `.slnx`, `.csproj`
**Example output**:
@@ -46,8 +55,17 @@ projgraph erd ./Migrations/MyDbContextModelSnapshot.cs
# Save to file
projgraph erd ./Data/MyDbContext.cs > database-schema.md
+
+# Generate without title header
+projgraph erd ./Data/MyDbContext.cs --show-title false
```
+**Settings**:
+
+- `[path]`: Optional path to `.cs` file. Searches current directory if not specified.
+- `-c|--context `: Optional context/snapshot name.
+- `--show-title `: Include diagram title. Default: `true`.
+
**Features**:
- Detects entities, properties, and relationships from source or snapshots
@@ -83,10 +101,21 @@ Generate Mermaid Class Diagram for a specific class and its hierarchy.
# Analyze a specific class and discover its base types and dependencies
projgraph classdiagram ./Models/Admin.cs
-# Specify depth of discovery (default: 3)
+# Specify depth of discovery (default: 1)
projgraph classdiagram ./Models/Admin.cs --depth 5
+
+# Generate without title header
+projgraph classdiagram ./Models/Admin.cs --show-title false
```
+**Settings**:
+
+- ``: Path to the `.cs` file.
+- `-i|--inheritance`: Include base classes/interfaces. Default: `false`.
+- `-d|--dependencies`: Include dependent types. Default: `false`.
+- `--depth `: Max discovery depth. Default: `1`.
+- `--show-title `: Include diagram title. Default: `true`.
+
**Features**:
- Detects properties, fields, and inheritance (`<|--`)
diff --git a/src/ProjGraph.Lib.ClassDiagram/Rendering/MermaidClassDiagramRenderer.cs b/src/ProjGraph.Lib.ClassDiagram/Rendering/MermaidClassDiagramRenderer.cs
index 7dbbed4..d6cb5b0 100644
--- a/src/ProjGraph.Lib.ClassDiagram/Rendering/MermaidClassDiagramRenderer.cs
+++ b/src/ProjGraph.Lib.ClassDiagram/Rendering/MermaidClassDiagramRenderer.cs
@@ -13,13 +13,14 @@ public sealed class MermaidClassDiagramRenderer : IDiagramRenderer
/// Renders a ClassModel as a Mermaid class diagram.
///
/// The ClassModel containing the types, relationships, and an optional title to be rendered.
+ /// The options for rendering the diagram.
/// A string representation of the Mermaid class diagram.
- public string Render(ClassModel model)
+ public string Render(ClassModel model, DiagramOptions? options = null)
{
var sb = new StringBuilder();
sb.AppendLine("```mermaid");
- if (!string.IsNullOrWhiteSpace(model.Title))
+ if ((options?.ShowTitle ?? true) && !string.IsNullOrWhiteSpace(model.Title))
{
sb.AppendLine("---");
sb.AppendLine($"title: {model.Title}");
diff --git a/src/ProjGraph.Lib.Core/Abstractions/DiagramOptions.cs b/src/ProjGraph.Lib.Core/Abstractions/DiagramOptions.cs
new file mode 100644
index 0000000..7464a64
--- /dev/null
+++ b/src/ProjGraph.Lib.Core/Abstractions/DiagramOptions.cs
@@ -0,0 +1,7 @@
+namespace ProjGraph.Lib.Core.Abstractions;
+
+///
+/// Represents options for rendering a diagram.
+///
+/// Whether to include the title in the rendered output.
+public record DiagramOptions(bool ShowTitle = true);
\ No newline at end of file
diff --git a/src/ProjGraph.Lib.Core/Abstractions/IDiagramRenderer.cs b/src/ProjGraph.Lib.Core/Abstractions/IDiagramRenderer.cs
index 8451b15..4f7b400 100644
--- a/src/ProjGraph.Lib.Core/Abstractions/IDiagramRenderer.cs
+++ b/src/ProjGraph.Lib.Core/Abstractions/IDiagramRenderer.cs
@@ -10,6 +10,7 @@ public interface IDiagramRenderer
/// Renders the specified model into a string representation.
///
/// The model to render.
+ /// The options for rendering the diagram.
/// A string representation of the diagram.
- string Render(TModel model);
+ string Render(TModel model, DiagramOptions? options = null);
}
\ No newline at end of file
diff --git a/src/ProjGraph.Lib.EntityFramework/Rendering/MermaidErdRenderer.cs b/src/ProjGraph.Lib.EntityFramework/Rendering/MermaidErdRenderer.cs
index b4de1f8..91af577 100644
--- a/src/ProjGraph.Lib.EntityFramework/Rendering/MermaidErdRenderer.cs
+++ b/src/ProjGraph.Lib.EntityFramework/Rendering/MermaidErdRenderer.cs
@@ -14,15 +14,16 @@ public sealed class MermaidErdRenderer : IDiagramRenderer
/// Renders a Mermaid ERD diagram from the given Entity Framework model.
///
/// The EF model containing entities and relationships to be rendered.
+ /// The options for rendering the diagram.
///
/// A string representing the ERD in Mermaid syntax, which can be used to visualize the model.
///
- public string Render(EfModel model)
+ public string Render(EfModel model, DiagramOptions? options = null)
{
var sb = new StringBuilder();
sb.AppendLine("```mermaid");
- if (!string.IsNullOrWhiteSpace(model.ContextName))
+ if ((options?.ShowTitle ?? true) && !string.IsNullOrWhiteSpace(model.ContextName))
{
sb.AppendLine("---");
sb.AppendLine($"title: {model.ContextName}");
diff --git a/src/ProjGraph.Lib.ProjectGraph/Rendering/FlatGraphRenderer.cs b/src/ProjGraph.Lib.ProjectGraph/Rendering/FlatGraphRenderer.cs
index 08b6bcb..9cee7c7 100644
--- a/src/ProjGraph.Lib.ProjectGraph/Rendering/FlatGraphRenderer.cs
+++ b/src/ProjGraph.Lib.ProjectGraph/Rendering/FlatGraphRenderer.cs
@@ -1,4 +1,5 @@
using ProjGraph.Core.Models;
+using ProjGraph.Lib.Core.Abstractions;
using Spectre.Console;
namespace ProjGraph.Lib.ProjectGraph.Rendering;
@@ -12,17 +13,18 @@ public sealed class FlatGraphRenderer : SolutionGraphRendererBase
/// Renders a as a flat list of projects and their direct dependencies.
///
/// The to render.
+ /// The options for rendering the diagram.
/// A string representation of the solution graph rendered as a flat list.
///
/// This method renders each project in sorted order (by type and name) followed by its direct dependencies.
/// Projects involved in cyclic dependencies are highlighted in red. Cycle detection is performed using the
/// method.
///
- public override string Render(SolutionGraph graph)
+ public override string Render(SolutionGraph graph, DiagramOptions? options = null)
{
_writer.GetStringBuilder().Clear();
- RenderHeader(graph);
+ RenderHeader(graph, options);
var cyclicProjectIds = GetCyclicProjectIds(graph);
diff --git a/src/ProjGraph.Lib.ProjectGraph/Rendering/MermaidGraphRenderer.cs b/src/ProjGraph.Lib.ProjectGraph/Rendering/MermaidGraphRenderer.cs
index e7f449e..54b9296 100644
--- a/src/ProjGraph.Lib.ProjectGraph/Rendering/MermaidGraphRenderer.cs
+++ b/src/ProjGraph.Lib.ProjectGraph/Rendering/MermaidGraphRenderer.cs
@@ -13,13 +13,14 @@ public sealed class MermaidGraphRenderer : IDiagramRenderer
/// Renders a solution graph into a Mermaid.js graph definition.
///
/// The solution graph to render.
+ /// The options for rendering the diagram.
/// A string containing the Mermaid.js graph definition.
- public string Render(SolutionGraph graph)
+ public string Render(SolutionGraph graph, DiagramOptions? options = null)
{
var sb = new StringBuilder();
sb.AppendLine("```mermaid");
- if (!string.IsNullOrWhiteSpace(graph.Name))
+ if ((options?.ShowTitle ?? true) && !string.IsNullOrWhiteSpace(graph.Name))
{
sb.AppendLine("---");
sb.AppendLine($"title: {graph.Name}");
diff --git a/src/ProjGraph.Lib.ProjectGraph/Rendering/SolutionGraphRendererBase.cs b/src/ProjGraph.Lib.ProjectGraph/Rendering/SolutionGraphRendererBase.cs
index 179c687..a94dd9b 100644
--- a/src/ProjGraph.Lib.ProjectGraph/Rendering/SolutionGraphRendererBase.cs
+++ b/src/ProjGraph.Lib.ProjectGraph/Rendering/SolutionGraphRendererBase.cs
@@ -36,17 +36,23 @@ protected SolutionGraphRendererBase()
/// Renders the specified to a string representation.
///
/// The solution graph to render.
+ /// The options for rendering the diagram.
/// A string representation of the rendered graph.
- public abstract string Render(SolutionGraph graph);
+ public abstract string Render(SolutionGraph graph, DiagramOptions? options = null);
///
/// Renders the header section of the solution graph visualization.
///
/// The solution graph to render the header for.
- protected void RenderHeader(SolutionGraph graph)
+ /// The options for rendering the diagram.
+ protected void RenderHeader(SolutionGraph graph, DiagramOptions? options = null)
{
- var graphName = Markup.Escape(graph.Name.Trim());
- _console.Write(new Rule($"[yellow]Dependency Graph: {graphName}[/]") { Justification = Justify.Left });
+ if (options?.ShowTitle ?? true)
+ {
+ var graphName = Markup.Escape(graph.Name.Trim());
+ _console.Write(new Rule($"[yellow]Dependency Graph: {graphName}[/]") { Justification = Justify.Left });
+ }
+
_console.MarkupLine("[bold blue]Projects[/]");
}
@@ -86,9 +92,11 @@ protected void RenderCycleWarning(HashSet cyclicProjectIds)
protected static HashSet GetCyclicProjectIds(SolutionGraph graph)
{
var cycles = TarjanSccAlgorithm.FindStronglyConnectedComponents(graph);
- return cycles
+ return
+ [
+ .. cycles
.Where(c => c.Count > 1)
.SelectMany(c => c)
- .ToHashSet();
+ ];
}
}
\ No newline at end of file
diff --git a/src/ProjGraph.Lib.ProjectGraph/Rendering/TreeGraphRenderer.cs b/src/ProjGraph.Lib.ProjectGraph/Rendering/TreeGraphRenderer.cs
index 666b9f8..ef4b13f 100644
--- a/src/ProjGraph.Lib.ProjectGraph/Rendering/TreeGraphRenderer.cs
+++ b/src/ProjGraph.Lib.ProjectGraph/Rendering/TreeGraphRenderer.cs
@@ -1,4 +1,5 @@
using ProjGraph.Core.Models;
+using ProjGraph.Lib.Core.Abstractions;
using Spectre.Console;
namespace ProjGraph.Lib.ProjectGraph.Rendering;
@@ -12,17 +13,18 @@ public sealed class TreeGraphRenderer : SolutionGraphRendererBase
/// Renders a as a tree structure, displaying project dependencies hierarchically.
///
/// The to render.
+ /// The options for rendering the diagram.
/// A string representation of the solution graph rendered as a tree.
///
/// This method identifies root projects (those with no incoming dependencies) and renders each as a separate tree branch.
/// Projects involved in cyclic dependencies are highlighted in red, and cycle detection is performed using the
/// method.
///
- public override string Render(SolutionGraph graph)
+ public override string Render(SolutionGraph graph, DiagramOptions? options = null)
{
_writer.GetStringBuilder().Clear();
- RenderHeader(graph);
+ RenderHeader(graph, options);
// Identify incoming dependency counts to find roots
var incomingCounts = graph.Projects.ToDictionary(p => p.Id, _ => 0);
diff --git a/src/ProjGraph.Mcp/Program.cs b/src/ProjGraph.Mcp/Program.cs
index 0f8beb0..e2f6b0b 100644
--- a/src/ProjGraph.Mcp/Program.cs
+++ b/src/ProjGraph.Mcp/Program.cs
@@ -57,12 +57,15 @@ public async Task GetClassDiagram(
[Description("Whether to search for and include other classes used as properties or fields.")]
bool includeDependencies = false,
[Description("How many levels of relationships to follow (default: 1).")]
- int depth = 1)
+ int depth = 1,
+ [Description("Whether to include the title in the diagram (default: true).")]
+ bool showTitle = true)
{
try
{
var model = await classService.AnalyzeFileAsync(filePath, includeInheritance, includeDependencies, depth);
- return classRenderer.Render(model);
+
+ return classRenderer.Render(model, new DiagramOptions(showTitle));
}
catch (Exception ex)
{
@@ -74,12 +77,15 @@ public async Task GetClassDiagram(
[Description("Analyzes a .NET solution or project file and returns the dependency graph as a Mermaid diagram.")]
public string GetProjectGraph(
[Description("Absolute path to the project or solution file.")]
- string path)
+ string path,
+ [Description("Whether to include the title in the diagram (default: true).")]
+ bool showTitle = true)
{
try
{
var graph = graphService.BuildGraph(path);
- return graphRenderer.Render(graph);
+
+ return graphRenderer.Render(graph, new DiagramOptions(showTitle));
}
catch (Exception ex)
{
@@ -96,12 +102,15 @@ public async Task GetErd(
[Description("Absolute path to the DbContext .cs file.")]
string path,
[Description("Specific DbContext class name to use if multiple are present.")]
- string? contextName = null)
+ string? contextName = null,
+ [Description("Whether to include the title in the diagram (default: true).")]
+ bool showTitle = true)
{
try
{
var model = await efService.AnalyzeContextAsync(path, contextName);
- return erdRenderer.Render(model);
+
+ return erdRenderer.Render(model, new DiagramOptions(showTitle));
}
catch (Exception ex)
{
diff --git a/src/ProjGraph.Mcp/README.md b/src/ProjGraph.Mcp/README.md
index 6d22b58..b583faf 100644
--- a/src/ProjGraph.Mcp/README.md
+++ b/src/ProjGraph.Mcp/README.md
@@ -16,6 +16,7 @@ Analyzes a solution or project file and returns the dependency graph as a Mermai
**Parameters:**
- `path` (string): Absolute path to `.sln`, `.slnx`, or `.csproj` file
+- `show_title` (boolean, optional): Whether to include the title in the diagram (default: true)
**Returns:** Mermaid graph diagram code
@@ -35,6 +36,7 @@ Generates a Mermaid Entity Relationship Diagram from an EF Core `DbContext` or `
- `path` (string): Absolute path to `.cs` file containing a `DbContext` or `ModelSnapshot`
- `contextName` (string, optional): Specific class name if multiple exist in the file
+- `show_title` (boolean, optional): Whether to include the title in the diagram (default: true)
**Returns:** Mermaid ERD diagram code
@@ -68,6 +70,7 @@ related types in the workspace.
- `includeDependencies` (boolean, optional): Whether to search for and include other classes used as properties or
fields (default: false)
- `depth` (number, optional): How many levels of relationships to follow (default: 1)
+- `show_title` (boolean, optional): Whether to include the title in the diagram (default: true)
**Returns:** Mermaid class diagram code
diff --git a/tests/ProjGraph.Tests.Contract/McpClassDiagramTests.cs b/tests/ProjGraph.Tests.Contract/McpClassDiagramTests.cs
index 4750413..556446d 100644
--- a/tests/ProjGraph.Tests.Contract/McpClassDiagramTests.cs
+++ b/tests/ProjGraph.Tests.Contract/McpClassDiagramTests.cs
@@ -28,7 +28,7 @@ public void GetClassDiagram_ShouldHave_CorrectSignature()
// Assert method has Description attribute
var descAttr = method.GetCustomAttribute();
descAttr.Should().NotBeNull();
- descAttr!.Description.Should().Contain("class diagram");
+ descAttr.Description.Should().Contain("class diagram");
}
[Fact]
@@ -44,8 +44,24 @@ public void GetClassDiagram_ShouldHave_RequiredParameters()
pathParam.GetCustomAttribute().Should().NotBeNull();
// Check optional flags
- parameters.Should().ContainSingle(p => p.Name == "includeInheritance");
- parameters.Should().ContainSingle(p => p.Name == "includeDependencies");
- parameters.Should().ContainSingle(p => p.Name == "depth");
+ var inheritanceParam = parameters.Should().ContainSingle(p => p.Name == "includeInheritance").Which;
+ inheritanceParam.ParameterType.Should().Be();
+ inheritanceParam.IsOptional.Should().BeTrue();
+ inheritanceParam.DefaultValue.Should().Be(false);
+
+ var dependenciesParam = parameters.Should().ContainSingle(p => p.Name == "includeDependencies").Which;
+ dependenciesParam.ParameterType.Should().Be();
+ dependenciesParam.IsOptional.Should().BeTrue();
+ dependenciesParam.DefaultValue.Should().Be(false);
+
+ var depthParam = parameters.Should().ContainSingle(p => p.Name == "depth").Which;
+ depthParam.ParameterType.Should().Be();
+ depthParam.IsOptional.Should().BeTrue();
+ depthParam.DefaultValue.Should().Be(1);
+
+ var titleParam = parameters.Should().ContainSingle(p => p.Name == "showTitle").Which;
+ titleParam.ParameterType.Should().Be();
+ titleParam.IsOptional.Should().BeTrue();
+ titleParam.DefaultValue.Should().Be(true);
}
}
\ No newline at end of file
diff --git a/tests/ProjGraph.Tests.Contract/McpContractTests.cs b/tests/ProjGraph.Tests.Contract/McpContractTests.cs
index 22c9231..837aa97 100644
--- a/tests/ProjGraph.Tests.Contract/McpContractTests.cs
+++ b/tests/ProjGraph.Tests.Contract/McpContractTests.cs
@@ -63,15 +63,23 @@ public void GetProjectGraph_ShouldHave_PathParameter()
}
[Fact]
- public void GetProjectGraph_ShouldHave_OnlyRequiredParameters()
+ public void GetProjectGraph_ShouldHave_Parameters()
{
// Arrange
var type = typeof(ProjGraphTools);
var method = type.GetMethod("GetProjectGraph");
var parameters = method!.GetParameters();
- // Assert only required parameters exist (path is the only required parameter per spec)
- parameters.Should().HaveCount(1, "GetProjectGraph should only have the 'path' parameter");
- parameters[0].Name.Should().Be("path");
+ // Assert parameters exist
+ parameters.Should().HaveCount(2, "GetProjectGraph should have 'path' and 'show_title' parameters");
+
+ var pathParam = parameters.Should().ContainSingle(p => p.Name == "path").Which;
+ pathParam.ParameterType.Should().Be();
+ pathParam.IsOptional.Should().BeFalse();
+
+ var titleParam = parameters.Should().ContainSingle(p => p.Name == "showTitle").Which;
+ titleParam.ParameterType.Should().Be();
+ titleParam.IsOptional.Should().BeTrue();
+ titleParam.DefaultValue.Should().Be(true);
}
}
\ No newline at end of file
diff --git a/tests/ProjGraph.Tests.Contract/McpErdContractTests.cs b/tests/ProjGraph.Tests.Contract/McpErdContractTests.cs
index c6537e9..2ccfd05 100644
--- a/tests/ProjGraph.Tests.Contract/McpErdContractTests.cs
+++ b/tests/ProjGraph.Tests.Contract/McpErdContractTests.cs
@@ -86,16 +86,28 @@ public void GetErd_ShouldHave_OptionalContextNameParameter()
}
[Fact]
- public void GetErd_ShouldHave_ExactlyTwoParameters()
+ public void GetErd_ShouldHave_Parameters()
{
// Arrange
var type = typeof(ProjGraphTools);
var method = type.GetMethod("GetErd");
var parameters = method!.GetParameters();
- // Assert exactly two parameters exist (path required, contextName optional)
- parameters.Should().HaveCount(2, "GetErd should have exactly 2 parameters: path and contextName");
- parameters[0].Name.Should().Be("path");
- parameters[1].Name.Should().Be("contextName");
+ // Assert parameters exist
+ parameters.Should().HaveCount(3, "GetErd should have 3 parameters: path, contextName, and show_title");
+
+ var pathParam = parameters.Should().ContainSingle(p => p.Name == "path").Which;
+ pathParam.ParameterType.Should().Be();
+ pathParam.IsOptional.Should().BeFalse();
+
+ var contextParam = parameters.Should().ContainSingle(p => p.Name == "contextName").Which;
+ contextParam.ParameterType.Should().Be();
+ contextParam.IsOptional.Should().BeTrue();
+ contextParam.DefaultValue.Should().BeNull();
+
+ var titleParam = parameters.Should().ContainSingle(p => p.Name == "showTitle").Which;
+ titleParam.ParameterType.Should().Be();
+ titleParam.IsOptional.Should().BeTrue();
+ titleParam.DefaultValue.Should().Be(true);
}
}
\ No newline at end of file
diff --git a/tests/ProjGraph.Tests.Unit.ClassDiagram/MermaidClassDiagramRendererTests.cs b/tests/ProjGraph.Tests.Unit.ClassDiagram/MermaidClassDiagramRendererTests.cs
index 672fc52..7ec2342 100644
--- a/tests/ProjGraph.Tests.Unit.ClassDiagram/MermaidClassDiagramRendererTests.cs
+++ b/tests/ProjGraph.Tests.Unit.ClassDiagram/MermaidClassDiagramRendererTests.cs
@@ -1,5 +1,6 @@
using ProjGraph.Core.Models;
using ProjGraph.Lib.ClassDiagram.Rendering;
+using ProjGraph.Lib.Core.Abstractions;
namespace ProjGraph.Tests.Unit.ClassDiagram;
@@ -46,6 +47,26 @@ public void Render_WithClassAndMembers_ReturnsCorrectMermaid()
result.Should().Contain("+Dictionary~string, string~ Metadata");
}
+ [Fact]
+ public void Render_WithShowTitle_ShouldShowTitle()
+ {
+ var model = new ClassModel("MyTitle", [], []);
+ var result = _renderer.Render(model);
+
+ result.Should().Contain("---");
+ result.Should().Contain("title: MyTitle");
+ }
+
+ [Fact]
+ public void Render_WithShowTitleFalse_ShouldNotShowTitle()
+ {
+ var model = new ClassModel("MyTitle", [], []);
+ var result = _renderer.Render(model, new DiagramOptions(false));
+
+ result.Should().NotContain("---");
+ result.Should().NotContain("title: MyTitle");
+ }
+
[Fact]
public void Render_WithInheritance_ReturnsCorrectMermaid()
{
diff --git a/tests/ProjGraph.Tests.Unit.EntityFramework/MermaidErdRendererTests.cs b/tests/ProjGraph.Tests.Unit.EntityFramework/MermaidErdRendererTests.cs
index 2711955..c04e92d 100644
--- a/tests/ProjGraph.Tests.Unit.EntityFramework/MermaidErdRendererTests.cs
+++ b/tests/ProjGraph.Tests.Unit.EntityFramework/MermaidErdRendererTests.cs
@@ -1,4 +1,5 @@
using ProjGraph.Core.Models;
+using ProjGraph.Lib.Core.Abstractions;
using ProjGraph.Lib.EntityFramework.Rendering;
namespace ProjGraph.Tests.Unit.EntityFramework;
@@ -51,6 +52,34 @@ public void Render_ShouldHandleEmptyModel()
result.Should().Contain("```");
}
+ [Fact]
+ public void Render_ShouldShowTitle()
+ {
+ // Arrange
+ var model = new EfModel { ContextName = "MyContext", Entities = [] };
+
+ // Act
+ var result = _renderer.Render(model);
+
+ // Assert
+ result.Should().Contain("---");
+ result.Should().Contain("title: MyContext");
+ }
+
+ [Fact]
+ public void Render_ShouldNotShowTitle_WhenShowTitleIsFalse()
+ {
+ // Arrange
+ var model = new EfModel { ContextName = "MyContext", Entities = [] };
+
+ // Act
+ var result = _renderer.Render(model, new DiagramOptions(false));
+
+ // Assert
+ result.Should().NotContain("---");
+ result.Should().NotContain("title: MyContext");
+ }
+
[Fact]
public void Render_ShouldMarkPrimaryKeys()
{
diff --git a/tests/ProjGraph.Tests.Unit.ProjectGraph/MermaidGraphRendererTests.cs b/tests/ProjGraph.Tests.Unit.ProjectGraph/MermaidGraphRendererTests.cs
index 77d2b24..bdbc523 100644
--- a/tests/ProjGraph.Tests.Unit.ProjectGraph/MermaidGraphRendererTests.cs
+++ b/tests/ProjGraph.Tests.Unit.ProjectGraph/MermaidGraphRendererTests.cs
@@ -1,4 +1,5 @@
using ProjGraph.Core.Models;
+using ProjGraph.Lib.Core.Abstractions;
using ProjGraph.Lib.ProjectGraph.Rendering;
namespace ProjGraph.Tests.Unit.ProjectGraph;
@@ -99,7 +100,7 @@ public void Render_ShouldNotLabelLibraryProjects()
}
[Fact]
- public void Render_ShouldIncludeTitleFromSolutionName()
+ public void Render_ShouldShowTitleFromSolutionName()
{
// Arrange
var graph = new SolutionGraph("MySolution", "MySolution.sln", [], []);
@@ -112,6 +113,20 @@ public void Render_ShouldIncludeTitleFromSolutionName()
result.Should().Contain("title: MySolution");
}
+ [Fact]
+ public void Render_ShouldNotShowTitle_WhenShowTitleIsFalse()
+ {
+ // Arrange
+ var graph = new SolutionGraph("MySolution", "MySolution.sln", [], []);
+
+ // Act
+ var result = _renderer.Render(graph, new DiagramOptions(false));
+
+ // Assert
+ result.Should().NotContain("---");
+ result.Should().NotContain("title: MySolution");
+ }
+
[Fact]
public void Render_ShouldHandleEmptyGraph()
{
@@ -305,7 +320,7 @@ public void Render_ShouldOrderProjectsAndDependenciesByName()
var lines = result.Split('\n', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
// Projects should be ordered A, B, C
- var projectLines = lines.Where(l => l.Contains("[")).ToList();
+ var projectLines = lines.Where(l => l.Contains('[')).ToList();
projectLines[0].Should().Contain("ProjectA");
projectLines[1].Should().Contain("ProjectB");
projectLines[2].Should().Contain("ProjectC");