Skip to content

Commit 648d18b

Browse files
robertmclawsclaude
andcommitted
Add renderer-level tests for explicit template navigation sections
The parser-layer tests (ParseNavigationConfig_WithTabsElement_PopulatesTabsNotPages etc.) already verified that Pages comes back null when only Tabs are defined in XML. However, the actual bug was one layer deeper — in MintlifyRenderer.ProcessAsync, which called PopulateNavigationFromPath and injected a spurious pages block regardless. This adds: - contentOnly parameter to ConfigureTestWithTemplate so tests can invoke ProcessAsync([]) (documentation-only mode) with HasMintlifyTemplate set - ExplicitTemplateTabs_ContentOnly_HasTabsAndNoPages - ExplicitTemplateTabs_WithAssembly_HasOnlyTabsAndNoPages (regression) - ExplicitTemplateAnchors_ContentOnly_HasAnchorsAndNoPages - ExplicitTemplateProducts_ContentOnly_HasProductsAndNoPages Each test asserts that Navigation.Pages is null in the deserialized docs.json when the template defines an explicit navigation section type, which is the behavior introduced by the MintlifyRenderer fix. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 89c4049 commit 648d18b

1 file changed

Lines changed: 182 additions & 1 deletion

File tree

src/CloudNimble.DotNetDocs.Tests.Mintlify/Renderers/MintlifyRendererNavigationTypeTests.cs

Lines changed: 182 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,14 @@ public class MintlifyRendererNavigationTypeTests : DotNetDocsTestBase
3838
/// Configures test host with a specific template and navigation configuration.
3939
/// This must be called before TestSetup() to ensure the configuration is set before services are built.
4040
/// </summary>
41-
private void ConfigureTestWithTemplate(DocsJsonConfig? template, DocsNavigationConfig? navConfig = null)
41+
/// <param name="template">The DocsJsonConfig template to use, or null for no template.</param>
42+
/// <param name="navConfig">Optional navigation configuration to override defaults.</param>
43+
/// <param name="contentOnly">
44+
/// When <see langword="true"/>, sets <c>HasMintlifyTemplate = true</c> on the project context so that
45+
/// <see cref="DocumentationManager.ProcessAsync(System.Collections.Generic.IEnumerable{System.ValueTuple{string,string}})"/>
46+
/// with an empty assembly list still runs the renderer pipeline (content-only mode).
47+
/// </param>
48+
private void ConfigureTestWithTemplate(DocsJsonConfig? template, DocsNavigationConfig? navConfig = null, bool contentOnly = false)
4249
{
4350
_testOutputPath = Path.Combine(Path.GetTempPath(), $"MintlifyNavigationTypeTest_{Guid.NewGuid()}");
4451
Directory.CreateDirectory(_testOutputPath);
@@ -59,6 +66,10 @@ private void ConfigureTestWithTemplate(DocsJsonConfig? template, DocsNavigationC
5966
{
6067
ctx.DocumentationRootPath = _testOutputPath;
6168
ctx.ApiReferencePath = string.Empty;
69+
if (contentOnly)
70+
{
71+
ctx.HasMintlifyTemplate = true;
72+
}
6273
});
6374
});
6475
});
@@ -333,6 +344,176 @@ public async Task ApplyNavigationType_WithInvalidType_UsesDefaultBehavior()
333344

334345
#endregion
335346

347+
#region Explicit Template Navigation Section Tests
348+
349+
/// <summary>
350+
/// Regression test: when a template defines explicit Tabs in the Navigation config, the renderer
351+
/// must not auto-generate a parallel pages block from disk discovery (content-only mode).
352+
/// </summary>
353+
[TestMethod]
354+
public async Task ExplicitTemplateTabs_ContentOnly_HasTabsAndNoPages()
355+
{
356+
// Arrange
357+
ConfigureTestWithTemplate(
358+
new DocsJsonConfig
359+
{
360+
Name = "Test Docs",
361+
Theme = "mint",
362+
Colors = new ColorsConfig { Primary = "#000000" },
363+
Navigation = new NavigationConfig
364+
{
365+
Tabs =
366+
[
367+
new TabConfig { Tab = "Guides", Href = "/guides", Pages = ["guides/index"] },
368+
new TabConfig { Tab = "API Reference", Href = "/api", Pages = ["api/index"] }
369+
]
370+
}
371+
},
372+
contentOnly: true);
373+
374+
var documentationManager = GetService<DocumentationManager>();
375+
376+
// Act
377+
await documentationManager.ProcessAsync([]);
378+
379+
// Assert
380+
var docsJsonPath = Path.Combine(_testOutputPath, "docs.json");
381+
File.Exists(docsJsonPath).Should().BeTrue();
382+
383+
var json = File.ReadAllText(docsJsonPath);
384+
var config = JsonSerializer.Deserialize<DocsJsonConfig>(json, MintlifyConstants.JsonSerializerOptions);
385+
386+
config.Should().NotBeNull();
387+
config!.Navigation.Tabs.Should().HaveCount(2, "both template-defined tabs should be present");
388+
config.Navigation.Tabs![0].Tab.Should().Be("Guides");
389+
config.Navigation.Tabs![1].Tab.Should().Be("API Reference");
390+
config.Navigation.Pages.Should().BeNull("explicit tabs navigation must not produce a spurious pages block");
391+
}
392+
393+
/// <summary>
394+
/// Regression test: when a template defines explicit Tabs, auto-discovery must not inject a pages block
395+
/// even when a real assembly is also being processed.
396+
/// </summary>
397+
[TestMethod]
398+
public async Task ExplicitTemplateTabs_WithAssembly_HasOnlyTabsAndNoPages()
399+
{
400+
// Arrange
401+
ConfigureTestWithTemplate(new DocsJsonConfig
402+
{
403+
Name = "Test API",
404+
Theme = "mint",
405+
Colors = new ColorsConfig { Primary = "#000000" },
406+
Navigation = new NavigationConfig
407+
{
408+
Tabs =
409+
[
410+
new TabConfig { Tab = "Getting Started", Href = "/start", Pages = ["index"] },
411+
new TabConfig { Tab = "API Reference", Href = "/api", Pages = ["api/index"] }
412+
]
413+
}
414+
});
415+
416+
var assemblyPath = typeof(SimpleClass).Assembly.Location;
417+
var xmlPath = Path.ChangeExtension(assemblyPath, ".xml");
418+
var documentationManager = GetService<DocumentationManager>();
419+
420+
// Act
421+
await documentationManager.ProcessAsync(assemblyPath, xmlPath);
422+
423+
// Assert
424+
var docsJsonPath = Path.Combine(_testOutputPath, "docs.json");
425+
var json = File.ReadAllText(docsJsonPath);
426+
var config = JsonSerializer.Deserialize<DocsJsonConfig>(json, MintlifyConstants.JsonSerializerOptions);
427+
428+
config.Should().NotBeNull();
429+
config!.Navigation.Tabs.Should().HaveCount(2, "template-defined tabs should be preserved");
430+
config.Navigation.Pages.Should().BeNull("auto-discovery must not inject pages alongside explicit tabs even when an assembly is present");
431+
}
432+
433+
/// <summary>
434+
/// Verifies that a template with explicit Anchors produces anchors and no pages in content-only mode.
435+
/// </summary>
436+
[TestMethod]
437+
public async Task ExplicitTemplateAnchors_ContentOnly_HasAnchorsAndNoPages()
438+
{
439+
// Arrange
440+
ConfigureTestWithTemplate(
441+
new DocsJsonConfig
442+
{
443+
Name = "Test Docs",
444+
Theme = "mint",
445+
Colors = new ColorsConfig { Primary = "#000000" },
446+
Navigation = new NavigationConfig
447+
{
448+
Anchors =
449+
[
450+
new AnchorConfig { Anchor = "Documentation", Href = "/docs", Icon = "book", Pages = [] },
451+
new AnchorConfig { Anchor = "API", Href = "/api", Icon = "code", Pages = [] }
452+
]
453+
}
454+
},
455+
contentOnly: true);
456+
457+
var documentationManager = GetService<DocumentationManager>();
458+
459+
// Act
460+
await documentationManager.ProcessAsync([]);
461+
462+
// Assert
463+
var docsJsonPath = Path.Combine(_testOutputPath, "docs.json");
464+
var json = File.ReadAllText(docsJsonPath);
465+
var config = JsonSerializer.Deserialize<DocsJsonConfig>(json, MintlifyConstants.JsonSerializerOptions);
466+
467+
config.Should().NotBeNull();
468+
config!.Navigation.Anchors.Should().HaveCount(2, "both template-defined anchors should be present");
469+
config.Navigation.Anchors![0].Anchor.Should().Be("Documentation");
470+
config.Navigation.Anchors![1].Anchor.Should().Be("API");
471+
config.Navigation.Pages.Should().BeNull("explicit anchors navigation must not produce a spurious pages block");
472+
}
473+
474+
/// <summary>
475+
/// Verifies that a template with explicit Products produces products and no pages in content-only mode.
476+
/// </summary>
477+
[TestMethod]
478+
public async Task ExplicitTemplateProducts_ContentOnly_HasProductsAndNoPages()
479+
{
480+
// Arrange
481+
ConfigureTestWithTemplate(
482+
new DocsJsonConfig
483+
{
484+
Name = "Test Platform",
485+
Theme = "mint",
486+
Colors = new ColorsConfig { Primary = "#000000" },
487+
Navigation = new NavigationConfig
488+
{
489+
Products =
490+
[
491+
new ProductConfig { Product = "Core SDK", Href = "/core", Pages = ["core/index"] },
492+
new ProductConfig { Product = "Extensions", Href = "/ext", Pages = ["ext/index"] }
493+
]
494+
}
495+
},
496+
contentOnly: true);
497+
498+
var documentationManager = GetService<DocumentationManager>();
499+
500+
// Act
501+
await documentationManager.ProcessAsync([]);
502+
503+
// Assert
504+
var docsJsonPath = Path.Combine(_testOutputPath, "docs.json");
505+
var json = File.ReadAllText(docsJsonPath);
506+
var config = JsonSerializer.Deserialize<DocsJsonConfig>(json, MintlifyConstants.JsonSerializerOptions);
507+
508+
config.Should().NotBeNull();
509+
config!.Navigation.Products.Should().HaveCount(2, "both template-defined products should be present");
510+
config.Navigation.Products![0].Product.Should().Be("Core SDK");
511+
config.Navigation.Products![1].Product.Should().Be("Extensions");
512+
config.Navigation.Pages.Should().BeNull("explicit products navigation must not produce a spurious pages block");
513+
}
514+
515+
#endregion
516+
336517
}
337518

338519
}

0 commit comments

Comments
 (0)