diff --git a/test/docfx.Tests/SerializationTests/TestData/ApiPage/ApiPage.yml b/test/docfx.Tests/SerializationTests/TestData/ApiPage/ApiPage.yml new file mode 100644 index 00000000000..b25d28d2265 --- /dev/null +++ b/test/docfx.Tests/SerializationTests/TestData/ApiPage/ApiPage.yml @@ -0,0 +1,15 @@ +### YamlMime:ApiPage +title: Class Class1 +body: +- api1: Class Class1 + id: BuildFromAssembly_Class1 + metadata: + uid: BuildFromAssembly.Class1 + commentId: T:BuildFromAssembly.Class1 +languageId: csharp +metadata: + description: This is a test class. + listOfString: + - aaa + - bbb + - ccc diff --git a/test/docfx.Tests/SerializationTests/TestData/ApiPage/BuildFromAssembly.Class1.yml b/test/docfx.Tests/SerializationTests/TestData/ApiPage/BuildFromAssembly.Class1.yml new file mode 100644 index 00000000000..6311af13cfa --- /dev/null +++ b/test/docfx.Tests/SerializationTests/TestData/ApiPage/BuildFromAssembly.Class1.yml @@ -0,0 +1,57 @@ +### YamlMime:ApiPage +title: Class Class1 +body: +- api1: Class Class1 + id: BuildFromAssembly_Class1 + metadata: + uid: BuildFromAssembly.Class1 + commentId: T:BuildFromAssembly.Class1 +- facts: + - name: Namespace + value: + text: BuildFromAssembly + url: BuildFromAssembly.html + - name: Assembly + value: BuildFromAssembly.dll +- markdown: This is a test class. +- code: public class Class1 +- h4: Inheritance +- inheritance: + - text: object + url: https://learn.microsoft.com/dotnet/api/system.object + - text: Class1 + url: BuildFromAssembly.Class1.html +- h4: Inherited Members +- list: + - text: object.GetType() + url: https://learn.microsoft.com/dotnet/api/system.object.gettype + - text: object.MemberwiseClone() + url: https://learn.microsoft.com/dotnet/api/system.object.memberwiseclone + - text: object.ToString() + url: https://learn.microsoft.com/dotnet/api/system.object.tostring + - text: object.Equals(object?) + url: https://learn.microsoft.com/dotnet/api/system.object.equals#system-object-equals(system-object) + - text: object.Equals(object?, object?) + url: https://learn.microsoft.com/dotnet/api/system.object.equals#system-object-equals(system-object-system-object) + - text: object.ReferenceEquals(object?, object?) + url: https://learn.microsoft.com/dotnet/api/system.object.referenceequals + - text: object.GetHashCode() + url: https://learn.microsoft.com/dotnet/api/system.object.gethashcode +- h2: Constructors +- api3: Class1() + id: BuildFromAssembly_Class1__ctor + metadata: + uid: BuildFromAssembly.Class1.#ctor + commentId: M:BuildFromAssembly.Class1.#ctor +- code: public Class1() +- h2: Methods +- api3: HelloWorld() + id: BuildFromAssembly_Class1_HelloWorld + metadata: + uid: BuildFromAssembly.Class1.HelloWorld + commentId: M:BuildFromAssembly.Class1.HelloWorld +- markdown: Hello World. +- code: public static void HelloWorld() +languageId: csharp +metadata: + description: This is a test class. diff --git a/test/docfx.Tests/SerializationTests/TestData/ApiPage/BuildFromAssembly.Issue5432.yml b/test/docfx.Tests/SerializationTests/TestData/ApiPage/BuildFromAssembly.Issue5432.yml new file mode 100644 index 00000000000..969ab4f0858 --- /dev/null +++ b/test/docfx.Tests/SerializationTests/TestData/ApiPage/BuildFromAssembly.Issue5432.yml @@ -0,0 +1,43 @@ +### YamlMime:ApiPage +title: Struct Issue5432 +body: +- api1: Struct Issue5432 + id: BuildFromAssembly_Issue5432 + metadata: + uid: BuildFromAssembly.Issue5432 + commentId: T:BuildFromAssembly.Issue5432 +- facts: + - name: Namespace + value: + text: BuildFromAssembly + url: BuildFromAssembly.html + - name: Assembly + value: BuildFromAssembly.dll +- code: public struct Issue5432 +- h4: Inherited Members +- list: + - text: object.GetType() + url: https://learn.microsoft.com/dotnet/api/system.object.gettype + - text: object.ToString() + url: https://learn.microsoft.com/dotnet/api/system.object.tostring + - text: object.Equals(object?) + url: https://learn.microsoft.com/dotnet/api/system.object.equals#system-object-equals(system-object) + - text: object.Equals(object?, object?) + url: https://learn.microsoft.com/dotnet/api/system.object.equals#system-object-equals(system-object-system-object) + - text: object.ReferenceEquals(object?, object?) + url: https://learn.microsoft.com/dotnet/api/system.object.referenceequals + - text: object.GetHashCode() + url: https://learn.microsoft.com/dotnet/api/system.object.gethashcode +- h2: Properties +- api3: Name + id: BuildFromAssembly_Issue5432_Name + metadata: + uid: BuildFromAssembly.Issue5432.Name + commentId: P:BuildFromAssembly.Issue5432.Name +- code: public string Name { get; } +- h4: Property Value +- parameters: + - type: + - text: string + url: https://learn.microsoft.com/dotnet/api/system.string +languageId: csharp diff --git a/test/docfx.Tests/SerializationTests/TestData/ApiPage/BuildFromProject.Class1.Issue8696Attribute.yml b/test/docfx.Tests/SerializationTests/TestData/ApiPage/BuildFromProject.Class1.Issue8696Attribute.yml new file mode 100644 index 00000000000..5ac63efdba0 --- /dev/null +++ b/test/docfx.Tests/SerializationTests/TestData/ApiPage/BuildFromProject.Class1.Issue8696Attribute.yml @@ -0,0 +1,165 @@ +### YamlMime:ApiPage +title: Class Class1.Issue8696Attribute +body: +- api1: Class Class1.Issue8696Attribute + id: BuildFromProject_Class1_Issue8696Attribute + preview: "[DOCFX001](https://example.org/DOCFX001): 'BuildFromProject.Class1.Issue8696Attribute' is for evaluation purposes only and is subject to change or removal in future updates." + src: https://github.com/dotnet/docfx/blob/main/samples/seed/dotnet/project/Project/Class1.cs#L126 + metadata: + uid: BuildFromProject.Class1.Issue8696Attribute + commentId: T:BuildFromProject.Class1.Issue8696Attribute +- facts: + - name: Namespace + value: + text: BuildFromProject + url: BuildFromProject.html + - name: Assembly + value: BuildFromProject.dll +- code: 'public class Class1.Issue8696Attribute : Attribute' +- h4: Inheritance +- inheritance: + - text: object + url: https://learn.microsoft.com/dotnet/api/system.object + - text: Attribute + url: https://learn.microsoft.com/dotnet/api/system.attribute + - text: Class1.Issue8696Attribute + url: BuildFromProject.Class1.Issue8696Attribute.html +- h4: Inherited Members +- list: + - text: Attribute.Equals(object?) + url: https://learn.microsoft.com/dotnet/api/system.attribute.equals + - text: Attribute.GetCustomAttribute(Assembly, Type) + url: https://learn.microsoft.com/dotnet/api/system.attribute.getcustomattribute#system-attribute-getcustomattribute(system-reflection-assembly-system-type) + - text: Attribute.GetCustomAttribute(Assembly, Type, bool) + url: https://learn.microsoft.com/dotnet/api/system.attribute.getcustomattribute#system-attribute-getcustomattribute(system-reflection-assembly-system-type-system-boolean) + - text: Attribute.GetCustomAttribute(MemberInfo, Type) + url: https://learn.microsoft.com/dotnet/api/system.attribute.getcustomattribute#system-attribute-getcustomattribute(system-reflection-memberinfo-system-type) + - text: Attribute.GetCustomAttribute(MemberInfo, Type, bool) + url: https://learn.microsoft.com/dotnet/api/system.attribute.getcustomattribute#system-attribute-getcustomattribute(system-reflection-memberinfo-system-type-system-boolean) + - text: Attribute.GetCustomAttribute(Module, Type) + url: https://learn.microsoft.com/dotnet/api/system.attribute.getcustomattribute#system-attribute-getcustomattribute(system-reflection-module-system-type) + - text: Attribute.GetCustomAttribute(Module, Type, bool) + url: https://learn.microsoft.com/dotnet/api/system.attribute.getcustomattribute#system-attribute-getcustomattribute(system-reflection-module-system-type-system-boolean) + - text: Attribute.GetCustomAttribute(ParameterInfo, Type) + url: https://learn.microsoft.com/dotnet/api/system.attribute.getcustomattribute#system-attribute-getcustomattribute(system-reflection-parameterinfo-system-type) + - text: Attribute.GetCustomAttribute(ParameterInfo, Type, bool) + url: https://learn.microsoft.com/dotnet/api/system.attribute.getcustomattribute#system-attribute-getcustomattribute(system-reflection-parameterinfo-system-type-system-boolean) + - text: Attribute.GetCustomAttributes(Assembly) + url: https://learn.microsoft.com/dotnet/api/system.attribute.getcustomattributes#system-attribute-getcustomattributes(system-reflection-assembly) + - text: Attribute.GetCustomAttributes(Assembly, bool) + url: https://learn.microsoft.com/dotnet/api/system.attribute.getcustomattributes#system-attribute-getcustomattributes(system-reflection-assembly-system-boolean) + - text: Attribute.GetCustomAttributes(Assembly, Type) + url: https://learn.microsoft.com/dotnet/api/system.attribute.getcustomattributes#system-attribute-getcustomattributes(system-reflection-assembly-system-type) + - text: Attribute.GetCustomAttributes(Assembly, Type, bool) + url: https://learn.microsoft.com/dotnet/api/system.attribute.getcustomattributes#system-attribute-getcustomattributes(system-reflection-assembly-system-type-system-boolean) + - text: Attribute.GetCustomAttributes(MemberInfo) + url: https://learn.microsoft.com/dotnet/api/system.attribute.getcustomattributes#system-attribute-getcustomattributes(system-reflection-memberinfo) + - text: Attribute.GetCustomAttributes(MemberInfo, bool) + url: https://learn.microsoft.com/dotnet/api/system.attribute.getcustomattributes#system-attribute-getcustomattributes(system-reflection-memberinfo-system-boolean) + - text: Attribute.GetCustomAttributes(MemberInfo, Type) + url: https://learn.microsoft.com/dotnet/api/system.attribute.getcustomattributes#system-attribute-getcustomattributes(system-reflection-memberinfo-system-type) + - text: Attribute.GetCustomAttributes(MemberInfo, Type, bool) + url: https://learn.microsoft.com/dotnet/api/system.attribute.getcustomattributes#system-attribute-getcustomattributes(system-reflection-memberinfo-system-type-system-boolean) + - text: Attribute.GetCustomAttributes(Module) + url: https://learn.microsoft.com/dotnet/api/system.attribute.getcustomattributes#system-attribute-getcustomattributes(system-reflection-module) + - text: Attribute.GetCustomAttributes(Module, bool) + url: https://learn.microsoft.com/dotnet/api/system.attribute.getcustomattributes#system-attribute-getcustomattributes(system-reflection-module-system-boolean) + - text: Attribute.GetCustomAttributes(Module, Type) + url: https://learn.microsoft.com/dotnet/api/system.attribute.getcustomattributes#system-attribute-getcustomattributes(system-reflection-module-system-type) + - text: Attribute.GetCustomAttributes(Module, Type, bool) + url: https://learn.microsoft.com/dotnet/api/system.attribute.getcustomattributes#system-attribute-getcustomattributes(system-reflection-module-system-type-system-boolean) + - text: Attribute.GetCustomAttributes(ParameterInfo) + url: https://learn.microsoft.com/dotnet/api/system.attribute.getcustomattributes#system-attribute-getcustomattributes(system-reflection-parameterinfo) + - text: Attribute.GetCustomAttributes(ParameterInfo, bool) + url: https://learn.microsoft.com/dotnet/api/system.attribute.getcustomattributes#system-attribute-getcustomattributes(system-reflection-parameterinfo-system-boolean) + - text: Attribute.GetCustomAttributes(ParameterInfo, Type) + url: https://learn.microsoft.com/dotnet/api/system.attribute.getcustomattributes#system-attribute-getcustomattributes(system-reflection-parameterinfo-system-type) + - text: Attribute.GetCustomAttributes(ParameterInfo, Type, bool) + url: https://learn.microsoft.com/dotnet/api/system.attribute.getcustomattributes#system-attribute-getcustomattributes(system-reflection-parameterinfo-system-type-system-boolean) + - text: Attribute.GetHashCode() + url: https://learn.microsoft.com/dotnet/api/system.attribute.gethashcode + - text: Attribute.IsDefaultAttribute() + url: https://learn.microsoft.com/dotnet/api/system.attribute.isdefaultattribute + - text: Attribute.IsDefined(Assembly, Type) + url: https://learn.microsoft.com/dotnet/api/system.attribute.isdefined#system-attribute-isdefined(system-reflection-assembly-system-type) + - text: Attribute.IsDefined(Assembly, Type, bool) + url: https://learn.microsoft.com/dotnet/api/system.attribute.isdefined#system-attribute-isdefined(system-reflection-assembly-system-type-system-boolean) + - text: Attribute.IsDefined(MemberInfo, Type) + url: https://learn.microsoft.com/dotnet/api/system.attribute.isdefined#system-attribute-isdefined(system-reflection-memberinfo-system-type) + - text: Attribute.IsDefined(MemberInfo, Type, bool) + url: https://learn.microsoft.com/dotnet/api/system.attribute.isdefined#system-attribute-isdefined(system-reflection-memberinfo-system-type-system-boolean) + - text: Attribute.IsDefined(Module, Type) + url: https://learn.microsoft.com/dotnet/api/system.attribute.isdefined#system-attribute-isdefined(system-reflection-module-system-type) + - text: Attribute.IsDefined(Module, Type, bool) + url: https://learn.microsoft.com/dotnet/api/system.attribute.isdefined#system-attribute-isdefined(system-reflection-module-system-type-system-boolean) + - text: Attribute.IsDefined(ParameterInfo, Type) + url: https://learn.microsoft.com/dotnet/api/system.attribute.isdefined#system-attribute-isdefined(system-reflection-parameterinfo-system-type) + - text: Attribute.IsDefined(ParameterInfo, Type, bool) + url: https://learn.microsoft.com/dotnet/api/system.attribute.isdefined#system-attribute-isdefined(system-reflection-parameterinfo-system-type-system-boolean) + - text: Attribute.Match(object?) + url: https://learn.microsoft.com/dotnet/api/system.attribute.match + - text: Attribute.TypeId + url: https://learn.microsoft.com/dotnet/api/system.attribute.typeid + - text: object.Equals(object?) + url: https://learn.microsoft.com/dotnet/api/system.object.equals#system-object-equals(system-object) + - text: object.Equals(object?, object?) + url: https://learn.microsoft.com/dotnet/api/system.object.equals#system-object-equals(system-object-system-object) + - text: object.GetHashCode() + url: https://learn.microsoft.com/dotnet/api/system.object.gethashcode + - text: object.GetType() + url: https://learn.microsoft.com/dotnet/api/system.object.gettype + - text: object.MemberwiseClone() + url: https://learn.microsoft.com/dotnet/api/system.object.memberwiseclone + - text: object.ReferenceEquals(object?, object?) + url: https://learn.microsoft.com/dotnet/api/system.object.referenceequals + - text: object.ToString() + url: https://learn.microsoft.com/dotnet/api/system.object.tostring +- h2: Constructors +- api3: Issue8696Attribute(string?, int, int, string[]?, bool, Type?) + id: BuildFromProject_Class1_Issue8696Attribute__ctor_System_String_System_Int32_System_Int32_System_String___System_Boolean_System_Type_ + src: https://github.com/dotnet/docfx/blob/main/samples/seed/dotnet/project/Project/Class1.cs#L128 + metadata: + uid: BuildFromProject.Class1.Issue8696Attribute.#ctor(System.String,System.Int32,System.Int32,System.String[],System.Boolean,System.Type) + commentId: M:BuildFromProject.Class1.Issue8696Attribute.#ctor(System.String,System.Int32,System.Int32,System.String[],System.Boolean,System.Type) +- code: >- + [Class1.Issue8696("Changes the name of the server in the server list", 0, 0, null, false, null)] + + public Issue8696Attribute(string? description = null, int boundsMin = 0, int boundsMax = 0, string[]? validGameModes = null, bool hasMultipleSelections = false, Type? enumType = null) +- h4: Parameters +- parameters: + - name: description + type: + - text: string + url: https://learn.microsoft.com/dotnet/api/system.string + - '?' + optional: true + - name: boundsMin + type: + - text: int + url: https://learn.microsoft.com/dotnet/api/system.int32 + optional: true + - name: boundsMax + type: + - text: int + url: https://learn.microsoft.com/dotnet/api/system.int32 + optional: true + - name: validGameModes + type: + - text: string + url: https://learn.microsoft.com/dotnet/api/system.string + - '[' + - ']' + - '?' + optional: true + - name: hasMultipleSelections + type: + - text: bool + url: https://learn.microsoft.com/dotnet/api/system.boolean + optional: true + - name: enumType + type: + - text: Type + url: https://learn.microsoft.com/dotnet/api/system.type + - '?' + optional: true +languageId: csharp diff --git a/test/docfx.Tests/SerializationTests/YamlSerializationTest.ApiPage.cs b/test/docfx.Tests/SerializationTests/YamlSerializationTest.ApiPage.cs new file mode 100644 index 00000000000..c0db0066478 --- /dev/null +++ b/test/docfx.Tests/SerializationTests/YamlSerializationTest.ApiPage.cs @@ -0,0 +1,84 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics; +using System.IO; +using System.Net; +using System.Runtime.CompilerServices; +using System.Text.Json; +using Docfx.Build.ApiPage; +using Docfx.Build.ManagedReference; +using Docfx.Common; +using Docfx.DataContracts.ManagedReference; +using Docfx.Tests; +using FluentAssertions; +using Microsoft.Playwright; +using OneOf; +using YamlDotNet.Serialization; + +namespace docfx.Tests; + +public partial class YamlSerializationTest +{ + [Theory] + [TestData] + public void YamlSerializationTest_ApiPage(string path) + { + // Arrange + var model = LoadApiPage(path); // Note: Loading ApiPage YAML file requires custom logics. + + // Act/Assert + ValidateApiPageRoundTrip(model); + } + + /// + /// + /// + private static ApiPage LoadApiPage(string path) + { + path = PathHelper.ResolveTestDataPath(path); + + var deserializer = new DeserializerBuilder().WithAttemptingUnquotedStringTypeDeserialization() + .Build(); + + // 1. Deserialize ApiPage yaml as Dictionary + // 2. Serialize to json + // 3. Deserialize as ApiPage instance + var model = deserializer.Deserialize>(File.ReadAllText(path)); + var json = JsonSerializer.Serialize(model); + return JsonSerializer.Deserialize(json, ApiPage.JsonSerializerOptions); + } + + private static void ValidateApiPageRoundTrip(ApiPage model) + { + // Act + var yaml = ToYaml(model); + var result = ToApiPage(yaml); + + // Assert + + // ApiPage model can't be validated with `BeEquivalentTo` (See: https://github.com/dotnet/docfx/pull/10232) + // So compare serialized YAML contents. + ToYaml(result).Should().Be(yaml); + } + + private static string ToYaml(ApiPage model) + { + var deserializer = new DeserializerBuilder().WithAttemptingUnquotedStringTypeDeserialization().Build(); + + var json = JsonSerializer.Serialize(model, Docfx.Build.ApiPage.ApiPage.JsonSerializerOptions); + var obj = deserializer.Deserialize(json); + + using var writer = new StringWriter(); + YamlUtility.Serialize(writer, obj, "YamlMime:ApiPage"); + return writer.ToString(); + } + + private static ApiPage ToApiPage(string yaml) + { + var deserializer = new DeserializerBuilder().WithAttemptingUnquotedStringTypeDeserialization().Build(); + var dict = deserializer.Deserialize>(new StringReader(yaml)); + var json = JsonSerializer.Serialize(dict); + return JsonSerializer.Deserialize(json, ApiPage.JsonSerializerOptions); + } +}