feat: Add `categoryLayout` option for metadata generation by filzrev · Pull Request #9965 · dotnet/docfx
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using Docfx.Common; using Docfx.DataContracts.Common; using Docfx.Dotnet; using Docfx.Tests.Common; using FluentAssertions; namespace Docfx.Tests; public partial class MetadataCommandApiPageTocCategoryTest : TestBase { /// <summary> /// Use MetadataCommand to generate YAML files from a c# project and a VB project separately /// </summary> private readonly string _outputFolder; private readonly string _projectFolder; public MetadataCommandApiPageTocCategoryTest() { _outputFolder = GetRandomFolder(); _projectFolder = GetRandomFolder(); } [Fact] [Trait("Related", "docfx")] public async Task TestSeparatedPagesTocWithDefaulCategories() { var projectFile = Path.Combine(_projectFolder, "test.csproj"); var sourceFile = Path.Combine(_projectFolder, "test.cs"); File.Copy("Assets/test.csproj.sample.1", projectFile); File.Copy("Assets/test-multinamespace.cs.sample.1", sourceFile); await DotnetApiCatalog.Exec( new(new MetadataJsonItemConfig { Dest = _outputFolder, Src = new(new FileMappingItem(projectFile)) { Expanded = true }, NamespaceLayout = NamespaceLayout.Nested, CategoryLayout = CategoryLayout.Flattened, MemberLayout = MemberLayout.SeparatePages, OutputFormat = MetadataOutputFormat.ApiPage, }), new(), Directory.GetCurrentDirectory()); var file = Path.Combine(_outputFolder, "toc.yml"); Assert.True(File.Exists(file)); var tocViewModel = YamlUtility.Deserialize<TocItemViewModel[]>(file); var expected = YamlUtility.Deserialize<TocItemViewModel[]>(new StringReader(ExpectedData.Default)); // Assert tocViewModel.Should().BeEquivalentTo(expected); } [Fact] [Trait("Related", "docfx")] public async Task TestSeparatedPagesTocWithNestedCategories() { var projectFile = Path.Combine(_projectFolder, "test.csproj"); var sourceFile = Path.Combine(_projectFolder, "test.cs"); File.Copy("Assets/test.csproj.sample.1", projectFile); File.Copy("Assets/test-multinamespace.cs.sample.1", sourceFile); await DotnetApiCatalog.Exec( new(new MetadataJsonItemConfig { Dest = _outputFolder, Src = new(new FileMappingItem(projectFile)) { Expanded = true }, NamespaceLayout = NamespaceLayout.Nested, CategoryLayout = CategoryLayout.Nested, MemberLayout = MemberLayout.SeparatePages, OutputFormat = MetadataOutputFormat.ApiPage, }), new(), Directory.GetCurrentDirectory()); var file = Path.Combine(_outputFolder, "toc.yml"); Assert.True(File.Exists(file)); var tocViewModel = YamlUtility.Deserialize<TocItemViewModel[]>(file); var expected = YamlUtility.Deserialize<TocItemViewModel[]>(new StringReader(ExpectedData.Nested)); // Assert tocViewModel.Should().BeEquivalentTo(expected); } [Fact] [Trait("Related", "docfx")] public async Task TestSeparatedPagesTocWithNoneCategories() { var projectFile = Path.Combine(_projectFolder, "test.csproj"); var sourceFile = Path.Combine(_projectFolder, "test.cs"); File.Copy("Assets/test.csproj.sample.1", projectFile); File.Copy("Assets/test-multinamespace.cs.sample.1", sourceFile); await DotnetApiCatalog.Exec( new(new MetadataJsonItemConfig { Dest = _outputFolder, Src = new(new FileMappingItem(projectFile)) { Expanded = true }, NamespaceLayout = NamespaceLayout.Nested, CategoryLayout = CategoryLayout.None, MemberLayout = MemberLayout.SeparatePages, OutputFormat = MetadataOutputFormat.ApiPage, }), new(), Directory.GetCurrentDirectory()); var file = Path.Combine(_outputFolder, "toc.yml"); Assert.True(File.Exists(file)); var tocViewModel = YamlUtility.Deserialize<TocItemViewModel[]>(file); var expected = YamlUtility.Deserialize<TocItemViewModel[]>(new StringReader(ExpectedData.None)); // Assert tocViewModel.Should().BeEquivalentTo(expected); } private static class ExpectedData { public static readonly string Default = @" - name: OtherNamespace href: OtherNamespace.yml items: - name: Classes - name: OtherBar href: OtherNamespace.OtherBar.yml items: - name: Methods - name: FooBar<TArg> href: OtherNamespace.OtherBar.FooBar.yml - name: Samples href: Samples.yml items: - name: Foo href: Samples.Foo.yml items: - name: Sub href: Samples.Foo.Sub.yml items: - name: Classes - name: SubBar href: Samples.Foo.Sub.SubBar.yml items: - name: Methods - name: FooBar<TArg> href: Samples.Foo.Sub.SubBar.FooBar.yml - name: Classes - name: Bar href: Samples.Foo.Bar.yml items: - name: Methods - name: FooBar<TArg> href: Samples.Foo.Bar.FooBar.yml ".Trim(); public static readonly string Nested = @" - name: OtherNamespace href: OtherNamespace.yml items: - name: Classes items: - name: OtherBar href: OtherNamespace.OtherBar.yml items: - name: Methods items: - name: FooBar<TArg> href: OtherNamespace.OtherBar.FooBar.yml - name: Samples href: Samples.yml items: - name: Foo href: Samples.Foo.yml items: - name: Sub href: Samples.Foo.Sub.yml items: - name: Classes items: - name: SubBar href: Samples.Foo.Sub.SubBar.yml items: - name: Methods items: - name: FooBar<TArg> href: Samples.Foo.Sub.SubBar.FooBar.yml - name: Classes items: - name: Bar href: Samples.Foo.Bar.yml items: - name: Methods items: - name: FooBar<TArg> href: Samples.Foo.Bar.FooBar.yml ".Trim(); public static readonly string None = @" - name: OtherNamespace href: OtherNamespace.yml items: - name: OtherBar href: OtherNamespace.OtherBar.yml items: - name: FooBar<TArg> href: OtherNamespace.OtherBar.FooBar.yml - name: Samples href: Samples.yml items: - name: Foo href: Samples.Foo.yml items: - name: Sub href: Samples.Foo.Sub.yml items: - name: SubBar href: Samples.Foo.Sub.SubBar.yml items: - name: FooBar<TArg> href: Samples.Foo.Sub.SubBar.FooBar.yml - name: Bar href: Samples.Foo.Bar.yml items: - name: FooBar<TArg> href: Samples.Foo.Bar.FooBar.yml ".Trim(); } }