public void TestInvalidObjectAgainstSchema() { using var listener = new TestListenerScope("TestInvalidMetadataReference"); var schemaFile = CreateFile("template/schemas/mta.reference.test.schema.json", @" { ""$schema"": ""http://dotnet.github.io/docfx/schemas/v1.0/schema.json#"", ""id"": ""https://contoso.com/template/schemas/mta.reference.test.schema.json"", ""version"": ""1.0.0"", ""title"": ""MetadataReferenceTest"", ""description"": ""A simple test schema for sdp"", ""type"": ""object"", ""properties"": { ""metadata"": { ""type"": ""object"" } }, ""metadata"": ""/metadata"" } ", _templateFolder); var inputFile = CreateFile("invalid.yml", @"### YamlMime:MetadataReferenceTest metadata: Web Apps Documentation ", _inputFolder); FileCollection files = new FileCollection(_defaultFiles); files.Add(DocumentType.Article, new[] { inputFile }, _inputFolder); BuildDocument(files); var errors = listener.Items.Where(s => s.Code == "ViolateSchema").ToList(); Assert.Single(errors); }
public void TestInvalidObjectAgainstSchema() { using var listener = new TestListenerScope("TestInvalidMetadataReference"); var schemaFile = CreateFile("template/schemas/mta.reference.test.schema.json", @" { ""$schema"": ""http://dotnet.github.io/docfx/schemas/v1.0/schema.json#"", ""id"": ""https://contoso.com/template/schemas/mta.reference.test.schema.json"", ""version"": ""1.0.0"", ""title"": ""MetadataReferenceTest"", ""description"": ""A simple test schema for sdp"", ""type"": ""object"", ""properties"": { ""metadata"": { ""type"": ""object"" } }, ""metadata"": ""/metadata"" } ", _templateFolder); var inputFile = CreateFile("invalid.yml", @"### YamlMime:MetadataReferenceTest metadata: Web Apps Documentation ", _inputFolder); FileCollection files = new FileCollection(_defaultFiles); files.Add(DocumentType.Article, new[] { inputFile }, _inputFolder); BuildDocument(files); var errors = listener.Items.Where(s => s.Code == "InvalidInputFile").ToList(); Assert.Single(errors); Assert.Equal($"Unable to load file '{inputFile}' via processor 'MetadataReferenceTest': Schema validation failed. Please validate the file and make sure it conforms to schema 'MetadataReferenceTest' (https://contoso.com/template/schemas/mta.reference.test.schema.json): \nInvalid type. Expected Object but got String. Path 'metadata'.", errors[0].Message); }
public void TestInvalidObjectAgainstSchema() { using (var listener = new TestListenerScope("TestInvalidMetadataReference")) { var schemaFile = CreateFile("template/schemas/mta.reference.test.schema.json", @" { ""$schema"": ""http://dotnet.github.io/docfx/schemas/v1.0/schema.json#"", ""version"": ""1.0.0"", ""title"": ""MetadataReferenceTest"", ""description"": ""A simple test schema for sdp"", ""type"": ""object"", ""properties"": { ""metadata"": { ""type"": ""object"" } }, ""metadata"": ""/metadata"" } ", _templateFolder); var inputFile = CreateFile("invalid.yml", @"### YamlMime:MetadataReferenceTest metadata: Web Apps Documentation ", _inputFolder); FileCollection files = new FileCollection(_defaultFiles); files.Add(DocumentType.Article, new[] { inputFile }, _inputFolder); Assert.Throws <DocumentException>(() => BuildDocument(files)); var errors = listener.Items.Where(s => s.LogLevel == LogLevel.Error).ToList(); Assert.Single(errors); Assert.Equal($"Unable to load file: {inputFile} via processor: MetadataReferenceTest: Validation against \"http://dotnet.github.io/docfx/schemas/v1.0/schema.json#\" failed: \nInvalid type. Expected Object but got String. Path 'metadata'.", errors[0].Message); } }
public void TestLoaderWhenPreprocessorExists() { var file1 = CreateFile("a.primary.tmpl", string.Empty, _inputFolder); var file2 = CreateFile("a.primary.js", "exports.transform = function(){}", _inputFolder); using var listener = new TestListenerScope("TestLoaderWhenPreprocessorExists"); var templates = LoadAllTemplates(); Assert.Empty(listener.Items); Assert.Single(templates); var template = templates[0]; Assert.NotNull(template.Renderer); Assert.Equal(TemplateType.Primary, template.TemplateType); Assert.Equal("a.primary", template.Name); Assert.Equal("a", template.Type); Assert.Equal(string.Empty, template.Extension); Assert.NotNull(template.Preprocessor); Assert.False(template.ContainsGetOptions); Assert.True(template.ContainsModelTransformation); var output = template.TransformModel(new { a = 1 }); Assert.Null(output); }
public void TestLoaderWhenNoFileExists() { using (var listener = new TestListenerScope("NoTemplate")) { var renderers = LoadAllRenderers(); Assert.Equal(0, listener.Items.Count); Assert.Equal(0, renderers.Count); var file1 = CreateFile("a.js", string.Empty, _inputFolder); renderers = LoadAllRenderers(); Assert.Equal(0, listener.Items.Count); Assert.Equal(0, renderers.Count); // only allows file under root folder var file2 = CreateFile("sub/a.tmpl", string.Empty, _inputFolder); renderers = LoadAllRenderers(); Assert.Equal(0, listener.Items.Count); Assert.Equal(0, renderers.Count); var file3 = CreateFile("a.tmpl.js", string.Empty, _inputFolder); renderers = LoadAllRenderers(); Assert.Equal(0, listener.Items.Count); Assert.Equal(0, renderers.Count); } }
public void TestLoaderWhenNoFileExists() { using var listener = new TestListenerScope("NoTemplate"); var templates = LoadAllTemplates(); Assert.Empty(listener.Items); Assert.Empty(templates); var file1 = CreateFile("a.js", string.Empty, _inputFolder); templates = LoadAllTemplates(); Assert.Empty(listener.Items); Assert.Empty(templates); // only allows file under root folder var file2 = CreateFile("sub/a.tmpl", string.Empty, _inputFolder); templates = LoadAllTemplates(); Assert.Empty(listener.Items); Assert.Empty(templates); var file3 = CreateFile("a.tmpl.js", string.Empty, _inputFolder); templates = LoadAllTemplates(); Assert.Empty(listener.Items); Assert.Empty(templates); }
public void TestInvalidSchemaDefinition() { // Json.NET schema has limitation of 1000 calls per hour using (var listener = new TestListenerScope("TestInvalidMetadataReference")) { var schemaFile = CreateFile("template/schemas/mta.reference.test.schema.json", @" { ""$schema"": ""http://dotnet.github.io/docfx/schemas/v1.0/schema.json#"", ""version"": ""1.0.0"", ""title"": ""MetadataReferenceTest"", ""description"": ""A simple test schema for sdp"", ""type"": ""object"", ""properties"": { ""metadata"": { ""type"": ""string"", ""contentType"": ""unknown"" } } } ", _templateFolder); var inputFiles = Enumerable.Range(0, 1) .Select(s => CreateFile($"normal{s}.yml", @"### YamlMime:MetadataReferenceTest metadata: Web Apps Documentation ", _inputFolder)).ToArray(); FileCollection files = new FileCollection(_defaultFiles); files.Add(DocumentType.Article, inputFiles, _inputFolder); Assert.Throws <InvalidSchemaException>(() => BuildDocument(files)); } }
public void TestSchemaReachedLimits() { // Json.NET schema has limitation of 1000 calls per hour using (var listener = new TestListenerScope("TestInvalidMetadataReference")) { var schemaFile = CreateFile("template/schemas/limit.test.schema.json", @" { ""$schema"": ""http://dotnet.github.io/docfx/schemas/v1.0/schema.json#"", ""version"": ""1.0.0"", ""title"": ""LimitTest"", ""description"": ""A simple test schema for sdp"", ""type"": ""object"", ""properties"": { ""metadata"": { ""type"": ""string"" } } } ", _templateFolder); var inputFiles = Enumerable.Range(0, 2000) .Select(s => CreateFile($"normal{s}.yml", @"### YamlMime:LimitTest metadata: Web Apps Documentation ", _inputFolder)).ToArray(); FileCollection files = new FileCollection(_defaultFiles); files.Add(DocumentType.Article, inputFiles, _inputFolder); BuildDocument(files); Assert.Equal(2, listener.Items.Count); Assert.Single(listener.Items.Where(s => s.Message == "There is no template processing document type(s): LimitTest")); Assert.True(LimitationReached(listener)); } }
public void TestInvalidObjectAgainstSchema() { using (var listener = new TestListenerScope("TestInvalidMetadataReference")) { var schemaFile = CreateFile("template/schemas/mta.reference.test.schema.json", @" { ""$schema"": ""http://dotnet.github.io/docfx/schemas/v1.0/schema.json#"", ""version"": ""1.0.0"", ""title"": ""MetadataReferenceTest"", ""description"": ""A simple test schema for sdp"", ""type"": ""object"", ""properties"": { ""metadata"": { ""type"": ""object"" } }, ""metadata"": ""/metadata"" } ", _templateFolder); var inputFile = CreateFile("invalid.yml", @"### YamlMime:MetadataReferenceTest metadata: Web Apps Documentation ", _inputFolder); FileCollection files = new FileCollection(_defaultFiles); files.Add(DocumentType.Article, new[] { inputFile }, _inputFolder); Assert.Throws <InvalidSchemaException>(() => BuildDocument(files)); } }
public void TestCaseFromSchemaSpec() { using (var listener = new TestListenerScope("TestCaseFromSchemaSpec")) { var spec = File.ReadAllText(SpecPath); var input = InputMatcher.Match(spec).Groups[2].Value; var inputFileName = "landingPage1.yml"; var inputFile = CreateFile(inputFileName, input, _inputFolder); File.WriteAllText(_inputFolder + "/landingPage1.yml", input); var schema = SchemaMatcher.Match(spec).Groups[1].Value; var schemaFile = CreateFile("template/schemas/landingpage.schema.json", schema, _templateFolder); FileCollection files = new FileCollection(_defaultFiles); files.Add(DocumentType.Article, new[] { inputFile }, _inputFolder); BuildDocument(files); Assert.Equal(13, listener.Items.Count); Assert.Equal("There is no template processing document type(s): LandingPage", listener.Items.FirstOrDefault(s => s.Message.StartsWith("There")).Message); Assert.Equal(10, listener.Items.Count(s => s.Message.StartsWith("Invalid file link"))); var rawModelFilePath = GetRawModelFilePath(inputFileName); Assert.True(File.Exists(rawModelFilePath)); var rawModel = JsonUtility.Deserialize <JObject>(rawModelFilePath); Assert.Equal("world", rawModel["metadata"]["hello"].ToString()); Assert.Equal("Hello world!", rawModel["meta"].ToString()); Assert.Equal("/metadata", rawModel["metadata"]["path"].ToString()); Assert.Equal($"<p sourcefile=\"{_inputFolder}/landingPage1.yml\" sourcestartlinenumber=\"1\" sourceendlinenumber=\"1\">Create an application using <a href=\"app-service-web-tutorial-dotnet-sqldatabase.md\" data-raw-source=\"[.NET with Azure SQL DB](app-service-web-tutorial-dotnet-sqldatabase.md)\" sourcefile=\"{_inputFolder}/landingPage1.yml\" sourcestartlinenumber=\"1\" sourceendlinenumber=\"1\">.NET with Azure SQL DB</a> or <a href=\"app-service-web-tutorial-nodejs-mongodb-app.md\" data-raw-source=\"[Node.js with MongoDB](app-service-web-tutorial-nodejs-mongodb-app.md)\" sourcefile=\"{_inputFolder}/landingPage1.yml\" sourcestartlinenumber=\"1\" sourceendlinenumber=\"1\">Node.js with MongoDB</a></p>\n" , rawModel["sections"][1]["children"][0]["content"].ToString()); } }
public void TestLoaderWhenStandalonePreprocessorExists() { var file1 = CreateFile("a.ext.TMPL.js", "exports.transform = function(){}", _inputFolder); using (var listener = new TestListenerScope("TestLoaderWhenStandalonePreprocessorExists")) { var templates = LoadAllTemplates(); Assert.Equal(0, listener.Items.Count); Assert.Equal(1, templates.Count); var template = templates[0]; Assert.Null(template.Renderer); Assert.Equal(TemplateType.Default, template.TemplateType); Assert.Equal("a.ext", template.Name); Assert.Equal("a", template.Type); Assert.Equal(".ext", template.Extension); Assert.NotNull(template.Preprocessor); Assert.False(template.ContainsGetOptions); Assert.True(template.ContainsModelTransformation); var output = template.TransformModel(new { a = 1 }); Assert.Null(output); } }
public void TestContextObjectSDP() { using (var listener = new TestListenerScope("TestContextObjectSDP")) { var schemaFile = CreateFile("template/schemas/contextobject.schema.json", File.ReadAllText("TestData/schemas/contextobject.test.schema.json"), _templateFolder); var tocTemplate = CreateFile("template/toc.json.tmpl", "toc template", _templateFolder); var inputFileName = "co/active.yml"; var includeFile = CreateFile("a b/inc.md", @"**Include**", _inputFolder); var inputFile = CreateFile(inputFileName, @"### YamlMime:ContextObject breadcrumb_path: /absolute/toc.json toc_rel: ../a b/toc.md file_include: ../a b/inc.md uhfHeaderId: MSDocsHeader-DotNet empty: searchScope: - .NET ", _inputFolder); FileCollection files = new FileCollection(_defaultFiles); files.Add(DocumentType.Article, new[] { inputFile }, _inputFolder); BuildDocument(files); Assert.Equal(3, listener.Items.Count); Assert.NotNull(listener.Items.FirstOrDefault(s => s.Message.StartsWith("There is no template processing document type(s): ContextObject"))); Assert.NotNull(listener.Items.FirstOrDefault(s => s.Message.StartsWith("Invalid file link"))); listener.Items.Clear(); var rawModelFilePath = GetRawModelFilePath(inputFileName); Assert.True(File.Exists(rawModelFilePath)); var rawModel = JsonUtility.Deserialize <JObject>(rawModelFilePath); Assert.Equal("Hello world!", rawModel["meta"].ToString()); Assert.Equal("/absolute/toc.json", rawModel["breadcrumb_path"].ToString()); Assert.Equal("../a b/toc.md", rawModel["toc_rel"].ToString()); Assert.Equal($"<p sourcefile=\"{includeFile}\" sourcestartlinenumber=\"1\" sourceendlinenumber=\"1\"><strong>Include</strong></p>\n", rawModel["file_include"].ToString()); Assert.Equal("MSDocsHeader-DotNet", rawModel["uhfHeaderId"].ToString()); Assert.Equal($".NET", rawModel["searchScope"][0].ToString()); files = new FileCollection(_defaultFiles); files.Add(DocumentType.Article, new[] { inputFile }, _inputFolder); var tocFile = CreateFile("a b/toc.md", "### hello", _inputFolder); files.Add(DocumentType.Article, new[] { tocFile }, _inputFolder); BuildDocument(files); Assert.Equal(2, listener.Items.Count); Assert.NotNull(listener.Items.FirstOrDefault(s => s.Message.StartsWith("There is no template processing document type(s): ContextObject"))); Assert.True(File.Exists(rawModelFilePath)); rawModel = JsonUtility.Deserialize <JObject>(rawModelFilePath); Assert.Equal("Hello world!", rawModel["meta"].ToString()); Assert.Equal("/absolute/toc.json", rawModel["breadcrumb_path"].ToString()); Assert.Equal("../a%20b/toc.json", rawModel["toc_rel"].ToString()); Assert.Equal("MSDocsHeader-DotNet", rawModel["uhfHeaderId"].ToString()); Assert.Equal($".NET", rawModel["searchScope"][0].ToString()); } }
public void TestXrefResolver() { using var listener = new TestListenerScope("TestXrefResolver"); // arrange var schemaFile = CreateFile("template/schemas/mref.test.schema.json", File.ReadAllText("TestData/schemas/mref.test.schema.json"), _templateFolder); var templateXref = CreateFile( "template/partials/overview.tmpl", @"{{name}}:{{{summary}}}|{{#boolProperty}}{{intProperty}}{{/boolProperty}}|{{#monikers}}<span>{{.}}</span>{{/monikers}}", _templateFolder); var templateFile = CreateFile("template/ManagedReference.html.tmpl", @" {{#items}} {{#children}} <xref uid={{.}} template=""partials/overview.tmpl""/> {{/children}} {{/items}} ", _templateFolder); var inputFileName = "inputs/CatLibrary.ICat.yml"; var inputFile = CreateFile(inputFileName, File.ReadAllText("TestData/inputs/CatLibrary.ICat.yml"), _inputFolder); FileCollection files = new FileCollection(_defaultFiles); files.Add(DocumentType.Article, new[] { inputFile }, _inputFolder); // act BuildDocument(files); // assert Assert.Single(listener.Items); listener.Items.Clear(); var xrefspec = Path.Combine(_outputFolder, "xrefmap.yml"); var xrefmap = YamlUtility.Deserialize <XRefMap>(xrefspec); Assert.Equal(2, xrefmap.References.Count); Assert.Equal(8, xrefmap.References[0].Keys.Count); Assert.Equal(10, xrefmap.References[1].Keys.Count); Assert.Equal("ICat", xrefmap.References[0].Name); Assert.Equal("CatLibrary.ICat.CatLibrary.ICatExtension.Sleep(System.Int64)", xrefmap.References[0]["extensionMethods/0"]); var outputFileName = Path.ChangeExtension(inputFileName, ".html"); Assert.Equal(outputFileName, xrefmap.References[0].Href); Assert.NotNull(xrefmap.References[0]["summary"]); var outputFilePath = Path.Combine(_outputFolder, outputFileName); Assert.True(File.Exists(outputFilePath)); var outputFileContent = File.ReadAllLines(outputFilePath); Assert.Equal(@" eat:<p>eat event of cat. Every cat must implement this event. This method is within <a class=""xref"" href=""CatLibrary.ICat.html"">ICat</a></p> |666|<span>net472</span><span>netstandard2_0</span>".Split(new string[] { "\r\n", "\n" }, StringSplitOptions.None), outputFileContent); }
public void ProcessItemWithEmptyUidShouldFail() { var fileNames = new string[] { "invalid.yml" }; var files = new FileCollection(Directory.GetCurrentDirectory()); files.Add(DocumentType.Article, fileNames.Select(f => $"{YmlDataDirectory}/{f}"), TestDataDirectory); using var listener = new TestListenerScope(nameof(UniversalReferenceDocumentProcessorTest)); BuildDocument(files); Assert.NotNull(listener.Items); Assert.Single(listener.Items); Assert.Contains("Uid must not be null or empty", listener.Items[0].Message); }
public void TestLoaderWithValidInput() { using var listener = new TestListenerScope("TestLoaderWhenStandalonePreprocessorExists"); var preprocessor = Load("a.ext.TMPL.js", "exports.transform = function(model) { return model; }"); Assert.Empty(listener.Items); Assert.NotNull(preprocessor); Assert.False(preprocessor.ContainsGetOptions); Assert.True(preprocessor.ContainsModelTransformation); var input = new { a = 1 }; var output = preprocessor.TransformModel(input); Assert.Equal(input.a, ((dynamic)output).a); }
public void TestSingleFileLoaderWithValidInput() { var path = "a.tmpl"; var file1 = CreateFile(path, "{{name}}", _inputFolder); using var listener = new TestListenerScope("TestLoaderWithValidInput"); var renderer = Load(path); Assert.Empty(listener.Items); Assert.NotNull(renderer); var model = new { name = "model" }; var output = renderer.Render(model); Assert.Equal("model", output); }
public void TestXrefResolverShouldWarnWithEmptyUidReference() { using var listener = new TestListenerScope(nameof(TestXrefResolverShouldWarnWithEmptyUidReference)); // arrange var schemaFile = CreateFile("template/schemas/mref.test.schema.json", File.ReadAllText("TestData/schemas/mref.test.schema.json"), _templateFolder); var inputFileName = "inputs/CatLibrary.ICat.yml"; var inputFile = CreateFile(inputFileName, File.ReadAllText("TestData/inputs/EmptyUidReference.yml"), _inputFolder); FileCollection files = new FileCollection(_defaultFiles); files.Add(DocumentType.Article, new[] { inputFile }, _inputFolder); // act BuildDocument(files); // assert Assert.NotEmpty(listener.Items); Assert.Contains(listener.Items, i => i.Code == WarningCodes.Build.UidNotFound); }
public void TestLoaderWithValidInput() { var file1 = CreateFile("a.tmpl", "{{name}}", _inputFolder); using (var listener = new TestListenerScope("TestLoaderWithValidInput")) { var renderers = LoadAllRenderers(); Assert.Equal(0, listener.Items.Count); Assert.Equal(1, renderers.Count); var renderer = renderers[0]; Assert.NotNull(renderer); var model = new { name = "model" }; var output = renderer.Render(model); Assert.Equal("model", output); } }
public void TestInvalidMetadataReference() { using (var listener = new TestListenerScope("TestGeneralFeaturesInSDP")) { var schemaFile = CreateFile("template/schemas/mta.reference.test.schema.json", @" { ""$schema"": ""http://dotnet.github.io/docfx/schemas/v1.0/schema.json#"", ""version"": ""1.0.0"", ""title"": ""MetadataReferenceTest"", ""description"": ""A simple test schema for sdp"", ""type"": ""object"", ""properties"": { ""metadata"": { ""type"": ""string"" } }, ""metadata"": ""/metadata"" } ", _templateFolder); var inputFileName1 = "page1.yml"; var inputFile1 = CreateFile(inputFileName1, @"### YamlMime:MetadataReferenceTest title: Web Apps Documentation metadata: title: Azure Web Apps Documentation - Tutorials, API Reference meta.description: Learn how to use App Service Web Apps to build and host websites and web applications. ms.service: app-service ms.tgt_pltfrm: na ms.author: carolz sections: - title: 5-Minute Quickstarts toc_rel: ../a b/toc.md uhfHeaderId: MSDocsHeader-DotNet searchScope: - .NET ", _inputFolder); FileCollection files = new FileCollection(_defaultFiles); files.Add(DocumentType.Article, new[] { inputFile1 }, _inputFolder); Assert.Throws <InvalidJsonPointerException>(() => BuildDocument(files)); } }
public void TestLoaderWhenRendererExists() { var file1 = CreateFile("a.tmpl", string.Empty, _inputFolder); using var listener = new TestListenerScope("TestLoaderWhenRendererExists"); var templates = LoadAllTemplates(); Assert.Empty(listener.Items); Assert.Single(templates); var template = templates[0]; Assert.NotNull(template.Renderer); Assert.Equal(TemplateType.Default, template.TemplateType); Assert.Equal("a", template.Name); Assert.Equal("a", template.Type); Assert.Equal(string.Empty, template.Extension); Assert.Null(template.Preprocessor); Assert.False(template.ContainsGetOptions); Assert.False(template.ContainsModelTransformation); }
public void TestSchemaOverwriteWithGeneralMergeTypes() { using (var listener = new TestListenerScope("TestSchemaOverwriteWithGeneralMergeTypes")) { var schema = new Dictionary <string, object> { ["type"] = "object", ["title"] = "testmerger", ["version"] = "1.0.0", ["$schema"] = "http://dotnet.github.io/docfx/schemas/v1.0/schema.json#", ["properties"] = new Dictionary <string, object> { ["uid"] = new { contentType = "uid", }, ["ignoreValue"] = new { mergeType = "ignore" }, ["array"] = new { type = "array", items = new { properties = new Dictionary <string, object> { ["type"] = new { mergeType = "key" }, ["intArrayValue"] = new { mergeType = "ignore" } } } }, ["dict"] = new { type = "object", properties = new Dictionary <string, object> { ["uid"] = new { contentType = "uid" }, ["summary"] = new { contentType = "markdown" }, ["intArrayValue"] = new { mergeType = "replace" }, ["dict"] = new { type = "object", properties = new Dictionary <string, object> { ["uid"] = new { contentType = "uid" }, ["summary"] = new { contentType = "markdown" }, ["href"] = new { contentType = "href" }, ["xref"] = new { contentType = "xref" } } } } } }, }; var schemaFile = CreateFile("template/schemas/testmerger.schema.json", JsonUtility.Serialize(schema), _templateFolder); var inputFileName = "src.yml"; var inputFile = CreateFile(inputFileName, @"### YamlMime:testmerger uid: uid1 intValue: 1 boolValue: true stringValue: string ignoreValue: abc empty: stringArrayValue: - .NET intArrayValue: - 1 - 2 emptyArray: [] array: - type: type1 intValue: 1 boolValue: true stringValue: string ignoreValue: abc empty: stringArrayValue: - .NET intArrayValue: - 1 - 2 emptyArray: [] dict: uid: uid1.uid1 intValue: 1 boolValue: true stringValue: string empty: stringArrayValue: - .NET intArrayValue: - 1 - 2 emptyArray: [] dict: uid: uid1.uid1.uid1 summary: ""*Hello* [self](src.yml)"" href: src.yml xref: uid1 ", _inputFolder); var overwriteFile = CreateFile("overwrite/a.md", @"--- uid: uid1 ignoreValue: Should ignore intValue: 2 stringValue: string1 empty: notEmpty stringArrayValue: - Java intArrayValue: - 1 emptyArray: [ 1 ] summary: *content array: - type: type1 intValue: 2 boolValue: false stringValue: *content ignoreValue: abcdef empty: 3 stringArrayValue: - *content intArrayValue: - 3 dict: intValue: 3 boolValue: false stringValue: *content empty: 4 stringArrayValue: - .NET intArrayValue: - 4 --- Nice --- uid: uid1 dict: another: *content --- Cool --- uid: uid1.uid1 summary: *content --- Overwrite with content ", _inputFolder); FileCollection files = new FileCollection(_defaultFiles); files.Add(DocumentType.Article, new[] { inputFile }, _inputFolder); files.Add(DocumentType.Overwrite, new[] { overwriteFile }, _inputFolder); BuildDocument(files); // One plugin warning for yml and one plugin warning for overwrite file Assert.Equal(6, listener.Items.Count); Assert.NotNull(listener.Items.FirstOrDefault(s => s.Message.StartsWith("There is no template processing document type(s): testmerger"))); Assert.Equal(1, listener.Items.Count(s => s.Message.StartsWith("\"/stringArrayValue/0\" in overwrite object fails to overwrite \"/stringArrayValue\" for \"uid1\" because it does not match any existing item."))); Assert.Equal(1, listener.Items.Count(s => s.Message.StartsWith("\"/intArrayValue/0\" in overwrite object fails to overwrite \"/intArrayValue\" for \"uid1\" because it does not match any existing item."))); Assert.Equal(1, listener.Items.Count(s => s.Message.StartsWith("\"/emptyArray/0\" in overwrite object fails to overwrite \"/emptyArray\" for \"uid1\" because it does not match any existing item."))); Assert.Equal(1, listener.Items.Count(s => s.Message.StartsWith("\"/array/0/stringArrayValue/0\" in overwrite object fails to overwrite \"/array/0/stringArrayValue\" for \"uid1\" because it does not match any existing item."))); Assert.Equal(1, listener.Items.Count(s => s.Message.StartsWith("\"/dict/stringArrayValue/0\" in overwrite object fails to overwrite \"/dict/stringArrayValue\" for \"uid1\" because it does not match any existing item."))); listener.Items.Clear(); var rawModelFilePath = GetRawModelFilePath(inputFileName); Assert.True(File.Exists(rawModelFilePath)); var rawModel = JsonUtility.Deserialize <JObject>(rawModelFilePath); Assert.Equal("Hello world!", rawModel["meta"].Value <string>()); Assert.Equal(2, rawModel["intValue"].Value <int>()); Assert.Equal("string1", rawModel["stringValue"].Value <string>()); Assert.Equal("abc", rawModel["ignoreValue"].Value <string>()); Assert.Equal(true, rawModel["boolValue"].Value <bool>()); Assert.Equal("notEmpty", rawModel["empty"].Value <string>()); Assert.Equal(1, rawModel["stringArrayValue"].Count()); Assert.Equal(".NET", rawModel["stringArrayValue"][0].Value <string>()); Assert.Equal(2, rawModel["intArrayValue"].Count()); Assert.Equal(1, rawModel["intArrayValue"][0].Value <int>()); Assert.Equal(2, rawModel["intArrayValue"][1].Value <int>()); Assert.Equal(0, rawModel["emptyArray"].Count()); var array1 = rawModel["array"][0]; Assert.Equal(2, array1["intValue"].Value <int>()); Assert.Equal($"<p sourcefile=\"{overwriteFile}\" sourcestartlinenumber=\"34\" sourceendlinenumber=\"34\">Nice</p>\n", array1["stringValue"].Value <string>()); Assert.Equal("abcdef", array1["ignoreValue"].Value <string>()); Assert.Equal(false, array1["boolValue"].Value <bool>()); Assert.Equal(3, array1["empty"].Value <int>()); Assert.Equal(1, array1["stringArrayValue"].Count()); Assert.Equal(".NET", array1["stringArrayValue"][0].Value <string>()); Assert.Equal(2, array1["intArrayValue"].Count()); Assert.Equal(1, array1["intArrayValue"][0].Value <int>()); Assert.Equal(2, array1["intArrayValue"][1].Value <int>()); Assert.Equal(0, array1["emptyArray"].Count()); var dict = rawModel["dict"]; Assert.Equal(3, dict["intValue"].Value <int>()); Assert.Equal($"<p sourcefile=\"{overwriteFile}\" sourcestartlinenumber=\"34\" sourceendlinenumber=\"34\">Nice</p>\n", dict["stringValue"].Value <string>()); Assert.Equal(false, dict["boolValue"].Value <bool>()); Assert.Equal(4, dict["empty"].Value <int>()); Assert.Equal(1, dict["stringArrayValue"].Count()); Assert.Equal(".NET", dict["stringArrayValue"][0].Value <string>()); Assert.Equal(1, dict["intArrayValue"].Count()); Assert.Equal(4, dict["intArrayValue"][0].Value <int>()); Assert.Equal(0, dict["emptyArray"].Count()); Assert.Equal($"<p sourcefile=\"{overwriteFile}\" sourcestartlinenumber=\"41\" sourceendlinenumber=\"41\">Cool</p>\n", dict["another"].Value <string>()); Assert.Equal($"<p sourcefile=\"{overwriteFile}\" sourcestartlinenumber=\"47\" sourceendlinenumber=\"47\">Overwrite with content</p>\n", dict["summary"].Value <string>()); } }
private bool LimitationReached(TestListenerScope listener) { return(listener.Items.SingleOrDefault(s => s.Message.StartsWith("Limitation reached when validating")) != null); }
public void TestValidMetadataReferenceWithIncremental() { using (var listener = new TestListenerScope("TestGeneralFeaturesInSDP")) { var schemaFile = CreateFile("template/schemas/mta.reference.test.schema.json", @" { ""$schema"": ""http://dotnet.github.io/docfx/schemas/v1.0/schema.json#"", ""version"": ""1.0.0"", ""title"": ""MetadataReferenceTest"", ""description"": ""A simple test schema for sdp"", ""type"": ""object"", ""properties"": { ""metadata"": { ""type"": ""object"" }, ""href"": { ""type"": ""string"", ""contentType"": ""href"" } }, ""metadata"": ""/metadata"" } ", _templateFolder); var inputFileName1 = "page1.yml"; var inputFile1 = CreateFile(inputFileName1, @"### YamlMime:MetadataReferenceTest title: Web Apps Documentation metadata: title: Azure Web Apps Documentation - Tutorials, API Reference meta.description: Learn how to use App Service Web Apps to build and host websites and web applications. ms.service: app-service ms.tgt_pltfrm: na ms.author: carolz href: toc.md sections: - title: 5-Minute Quickstarts toc_rel: ../a b/toc.md uhfHeaderId: MSDocsHeader-DotNet searchScope: - .NET ", _inputFolder); var dependentMarkdown = CreateFile("toc.md", "# Hello", _inputFolder); var inputFileName2 = "page2.yml"; var inputFile2 = CreateFile(inputFileName2, @"### YamlMime:MetadataReferenceTest title: Web Apps Documentation ", _inputFolder); FileCollection files = new FileCollection(_defaultFiles); files.Add(DocumentType.Article, new[] { inputFile1, inputFile2, dependentMarkdown }, _inputFolder); using (new LoggerPhaseScope("FirstRound")) { BuildDocument(files); } Assert.Equal(3, listener.Items.Count); Assert.NotNull(listener.Items.FirstOrDefault(s => s.Message.StartsWith("There is no template processing document type(s): MetadataReferenceTest,Toc"))); listener.Items.Clear(); var rawModelFilePath = GetRawModelFilePath(inputFileName1); Assert.True(File.Exists(rawModelFilePath)); var rawModel = JsonUtility.Deserialize <JObject>(rawModelFilePath); Assert.Equal("overwritten", rawModel["metadata"]["meta"].ToString()); Assert.Equal("postbuild1", rawModel["metadata"]["postMeta"].ToString()); Assert.Equal("1", rawModel["metadata"]["another"].ToString()); Assert.Equal("app-service", rawModel["metadata"]["ms.service"].ToString()); var rawModelFilePath2 = GetRawModelFilePath(inputFileName2); Assert.True(File.Exists(rawModelFilePath2)); var rawModel2 = JsonUtility.Deserialize <JObject>(rawModelFilePath2); Assert.Equal("Hello world!", rawModel2["metadata"]["meta"].ToString()); Assert.Equal("2", rawModel2["metadata"]["another"].ToString()); Assert.Equal("postbuild2", rawModel2["metadata"]["postMeta"].ToString()); // change dependent markdown UpdateFile("toc.md", new string[] { "# Updated" }, _inputFolder); using (new LoggerPhaseScope("SecondRound")) { BuildDocument(files); } rawModel = JsonUtility.Deserialize <JObject>(rawModelFilePath); Assert.Equal("overwritten", rawModel["metadata"]["meta"].ToString()); Assert.Equal("1", rawModel["metadata"]["another"].ToString()); Assert.Equal("app-service", rawModel["metadata"]["ms.service"].ToString()); Assert.Equal("postbuild1", rawModel["metadata"]["postMeta"].ToString()); rawModel2 = JsonUtility.Deserialize <JObject>(rawModelFilePath2); Assert.Equal("Hello world!", rawModel2["metadata"]["meta"].ToString()); Assert.Equal("2", rawModel2["metadata"]["another"].ToString()); Assert.Equal("postbuild2", rawModel2["metadata"]["postMeta"].ToString()); } }
public void TestRef() { using (var listener = new TestListenerScope("TestRef")) { var schemaFile = CreateFile("template/schemas/general.test.schema.json", File.ReadAllText("TestData/schemas/general.test.schema.json"), _templateFolder); var templateFile = CreateFile("template/General.html.tmpl", @"{{#items}} {{#aggregatedExceptions}} {{{message}}} {{{inner.message}}} {{{inner.inner.message}}} {{/aggregatedExceptions}} {{#exception}} {{{message}}} {{/exception}} {{{description}}} {{/items}} ", _templateFolder); var inputFileName = "inputs/exp1.yml"; var inputFile = CreateFile(inputFileName, @"### YamlMime:General items: - exception: message: ""**Hello**"" - aggregatedExceptions: - message: ""1**Hello**"" inner: message: ""1.1**Hello**"" inner: message: ""1.1.1**Hello**"" - message: ""2**Hello**"" inner: message: ""2.1**Hello**"" inner: message: ""2.1.1**Hello**"" - message: ""3**Hello**"" inner: message: ""3.1**Hello**"" inner: message: ""3.1.1**Hello**"" - description: ""**outside**"" ", _inputFolder); FileCollection files = new FileCollection(_defaultFiles); files.Add(DocumentType.Article, new[] { inputFile }, _inputFolder); BuildDocument(files); Assert.Equal(1, listener.Items.Count); var xrefspec = Path.Combine(_outputFolder, "xrefmap.yml"); var xrefmap = YamlUtility.Deserialize <XRefMap>(xrefspec); Assert.Equal(0, xrefmap.References.Count); var outputFileName = Path.ChangeExtension(inputFileName, ".html"); var outputFilePath = Path.Combine(_outputFolder, outputFileName); Assert.True(File.Exists(outputFilePath)); Assert.Equal($@" <p><strong>Hello</strong></p> <p>1<strong>Hello</strong></p> <p>1.1<strong>Hello</strong></p> <p>1.1.1<strong>Hello</strong></p> <p>2<strong>Hello</strong></p> <p>2.1<strong>Hello</strong></p> <p>2.1.1<strong>Hello</strong></p> <p>3<strong>Hello</strong></p> <p>3.1<strong>Hello</strong></p> <p>3.1.1<strong>Hello</strong></p> <p><strong>outside</strong></p> " .Split(new string[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries), File.ReadAllLines(outputFilePath).Where(s => !string.IsNullOrWhiteSpace(s)).Select(s => s.Trim()).ToArray()); } }
public void TestUidWithPatternedTag() { using var listener = new TestListenerScope("TestUidWithPatternedTag"); var schemaFile = CreateFile("template/schemas/patterned.uid.test.schema.json", @" { ""$schema"": ""http://dotnet.github.io/docfx/schemas/v1.0/schema.json#"", ""version"": ""1.0.0"", ""title"": ""PatternedUid"", ""description"": ""A simple test schema for sdp's patterned uid"", ""type"": ""object"", ""properties"": { ""uid"": { ""type"": ""string"", ""tags"": [ ""patterned:uid"" ] } } } ", _templateFolder); var inputFile = CreateFile("PatternedUid.yml", @"### YamlMime:PatternedUid uid: azure.hello1 ", _inputFolder); FileCollection files = new FileCollection(_defaultFiles); files.Add(DocumentType.Article, new[] { inputFile }, _inputFolder); BuildDocument(files, new DocumentBuildParameters { Files = files, OutputBaseDir = _outputFolder, ApplyTemplateSettings = _applyTemplateSettings, TemplateManager = _templateManager, TagParameters = new Dictionary <string, JArray> { ["patterned:uid"] = JArray.FromObject(new List <string> { "^azure\\..*" }) }, }); Assert.Equal(2, listener.Items.Count); Assert.NotNull(listener.Items.FirstOrDefault(s => s.Message.StartsWith("There is no template processing document type(s): PatternedUid"))); listener.Items.Clear(); inputFile = CreateFile("PatternedUid2.yml", @"### YamlMime:PatternedUid uid: invalid.hello1 ", _inputFolder); files.Add(DocumentType.Article, new[] { inputFile }, _inputFolder); inputFile = CreateFile("PatternedUid3.yml", @"### YamlMime:PatternedUid uid: invalid.azure.hello2 ", _inputFolder); files.Add(DocumentType.Article, new[] { inputFile }, _inputFolder); var exception = Assert.Throws <DocumentException>(() => BuildDocument(files, new DocumentBuildParameters { Files = files, OutputBaseDir = _outputFolder, ApplyTemplateSettings = _applyTemplateSettings, TemplateManager = _templateManager, TagParameters = new Dictionary <string, JArray> { ["patterned:uid"] = JArray.FromObject(new List <string> { "^azure\\..*" }) }, })); Assert.Equal("InvalidPropertyFormat", exception.Code); Assert.Equal(0, listener.Items.Count(s => s.Code == ErrorCodes.Build.InvalidPropertyFormat)); }
public void TestFragmentsWithIncremental() { using (var listener = new TestListenerScope(nameof(TestFragmentsWithIncremental))) { // first build using (new LoggerPhaseScope("FirstBuild")) { BuildDocument(_files); } Assert.True(File.Exists(_rawModelFilePath)); var rawModel = JsonUtility.Deserialize <JObject>(_rawModelFilePath); Assert.Null(rawModel["summary"]); Assert.NotNull(listener.Items.FirstOrDefault(s => s.Message.StartsWith("There is no template processing document type(s): RESTMixedTest"))); ClearLog(listener.Items); // add fragments var mdFile = CreateFile( "Suppressions.yml.md", @"# `management.azure.com.advisor.suppressions` ## ``summary`` I add a summary. With [!include[invalid](invalid.md)]", _inputFolder); using (new LoggerPhaseScope("AddFragments")) { BuildDocument(_files); } Assert.True(File.Exists(_rawModelFilePath)); rawModel = JsonUtility.Deserialize <JObject>(_rawModelFilePath); Assert.NotNull(rawModel["summary"]); Assert.Contains("I add a summary", rawModel["summary"].ToString()); Assert.NotNull(listener.Items.FirstOrDefault(s => s.Message.StartsWith("There is no template processing document type(s): RESTMixedTest"))); Assert.NotNull(listener.Items.FirstOrDefault(s => s.Message.Contains("Cannot resolve") && s.Message.Contains("invalid.md"))); List <string> lastMessages; var messages = ClearLog(listener.Items); // modify fragments UpdateFile( "Suppressions.yml.md", new string[] { @"# `management.azure.com.advisor.suppressions`", "## ``summary``", "I update a summary.", "With [!include[invalid](invalid.md)]", }, _inputFolder); using (new LoggerPhaseScope("ModifyFragments")) { BuildDocument(_files); } Assert.True(File.Exists(_rawModelFilePath)); rawModel = JsonUtility.Deserialize <JObject>(_rawModelFilePath); Assert.NotNull(rawModel["summary"]); Assert.Contains("I update a summary", rawModel["summary"].ToString()); Assert.NotNull(listener.Items.FirstOrDefault(s => s.Message.StartsWith("There is no template processing document type(s): RESTMixedTest"))); Assert.NotNull(listener.Items.FirstOrDefault(s => s.Message.Contains("Cannot resolve") && s.Message.Contains("invalid.md"))); lastMessages = messages; messages = ClearLog(listener.Items); Assert.True(messages.SequenceEqual(lastMessages)); // rebuild using (new LoggerPhaseScope("Rebuild")) { BuildDocument(_files); } Assert.True(File.Exists(_rawModelFilePath)); rawModel = JsonUtility.Deserialize <JObject>(_rawModelFilePath); Assert.NotNull(rawModel["summary"]); Assert.Contains("I update a summary", rawModel["summary"].ToString()); Assert.NotNull(listener.Items.FirstOrDefault(s => s.Message.StartsWith("There is no template processing document type(s): RESTMixedTest"))); Assert.NotNull(listener.Items.FirstOrDefault(s => s.Message.Contains("Cannot resolve") && s.Message.Contains("invalid.md"))); lastMessages = messages; messages = ClearLog(listener.Items); Assert.True(messages.SequenceEqual(lastMessages)); } }
public void TestContextObjectSDP() { Environment.SetEnvironmentVariable("_op_systemMetadata", JsonUtility.ToJsonString(new Dictionary <string, object> { { "_op_publishTargetSiteHostName", "ppe.docs.microsoft.com" } })); using var listener = new TestListenerScope("TestContextObjectSDP"); var schemaFile = CreateFile("template/schemas/contextobject.schema.json", File.ReadAllText("TestData/schemas/contextobject.test.schema.json"), _templateFolder); var tocTemplate = CreateFile("template/toc.json.tmpl", "toc template", _templateFolder); // var coTemplate = CreateFile("template/contextobject.json.tmpl", "{{file_include2}}", _templateFolder); var inputFileName = "co/active.yml"; var includeFile = CreateFile("a b/inc.md", @"[root](../co/active.yml)", _inputFolder); var includeFile2 = CreateFile("c/d/inc.md", @"../../a b/toc.md", _inputFolder); var inputFile = CreateFile(inputFileName, @"### YamlMime:ContextObject breadcrumb_path: https://ppe.docs.microsoft.com/absolute/toc.json toc_rel: ../a b/toc.md file_include: ../a b/inc.md file_include2: ../c/d/inc.md uhfHeaderId: MSDocsHeader-DotNet empty: searchScope: - .NET ", _inputFolder); var inputFileName2 = "co/active2.yml"; var inputFile2 = CreateFile(inputFileName2, @"### YamlMime:ContextObject breadcrumb_path: https://live.docs.microsoft.com/absolute/toc.json ", _inputFolder); FileCollection files = new FileCollection(_defaultFiles); files.Add(DocumentType.Article, new[] { inputFile, inputFile2 }, _inputFolder); BuildDocument(files); Assert.Equal(5, listener.Items.Count); Assert.Equal(2, listener.Items.Count(s => s.Message.StartsWith($"Invalid file link:(~/{_inputFolder}/a b/toc.md)."))); Assert.NotNull(listener.Items.FirstOrDefault(s => s.Message.StartsWith("There is no template processing document type(s): ContextObject"))); Assert.NotNull(listener.Items.FirstOrDefault(s => s.Message.StartsWith("Invalid file link"))); listener.Items.Clear(); var rawModelFilePath = GetRawModelFilePath(inputFileName); Assert.True(File.Exists(rawModelFilePath)); var rawModel = JsonUtility.Deserialize <JObject>(rawModelFilePath); Assert.Equal("Hello world!", rawModel["meta"].Value <string>()); Assert.Equal("/absolute/toc.json", rawModel["breadcrumb_path"].Value <string>()); Assert.Equal("../a b/toc.md", rawModel["toc_rel"].Value <string>()); Assert.Equal($"<p sourcefile=\"{includeFile}\" sourcestartlinenumber=\"1\" sourceendlinenumber=\"1\" jsonPath=\"/file_include\"><a href=\"~/{inputFile}\" data-raw-source=\"[root](../co/active.yml)\" sourcefile=\"{includeFile}\" sourcestartlinenumber=\"1\" sourceendlinenumber=\"1\">root</a></p>\n", rawModel["file_include"].Value <string>()); Assert.Equal("../../a b/toc.md", rawModel["file_include2"].Value <string>()); Assert.Equal("MSDocsHeader-DotNet", rawModel["uhfHeaderId"].Value <string>()); Assert.Equal(".NET", rawModel["searchScope"][0].Value <string>()); var rawModelFilePath2 = GetRawModelFilePath(inputFileName2); Assert.True(File.Exists(rawModelFilePath2)); var rawModel2 = JsonUtility.Deserialize <JObject>(rawModelFilePath2); Assert.Equal("https://live.docs.microsoft.com/absolute/toc.json", rawModel2["breadcrumb_path"].Value <string>()); files = new FileCollection(_defaultFiles); files.Add(DocumentType.Article, new[] { inputFile }, _inputFolder); var tocFile = CreateFile("a b/toc.md", "### hello", _inputFolder); files.Add(DocumentType.Article, new[] { tocFile }, _inputFolder); BuildDocument(files); Assert.Equal(2, listener.Items.Count); Assert.NotNull(listener.Items.FirstOrDefault(s => s.Message.StartsWith("There is no template processing document type(s): ContextObject"))); Assert.True(File.Exists(rawModelFilePath)); rawModel = JsonUtility.Deserialize <JObject>(rawModelFilePath); Assert.Equal("Hello world!", rawModel["meta"].Value <string>()); Assert.Equal("/absolute/toc.json", rawModel["breadcrumb_path"].Value <string>()); Assert.Equal("../a%20b/toc.json", rawModel["toc_rel"].Value <string>()); Assert.Equal("MSDocsHeader-DotNet", rawModel["uhfHeaderId"].Value <string>()); Assert.Equal(".NET", rawModel["searchScope"][0].Value <string>()); Assert.Equal("../a%20b/toc.json", rawModel["file_include2"].Value <string>()); }
public void TestSchemaOverwriteWithGeneralSchemaOptions() { using (var listener = new TestListenerScope("TestSchemaOverwriteWithGeneralSchemaOptions")) { var templateFile = CreateFile("template/testmerger2.html.tmpl", @"<xref uid=""{{xref}}""/>", _templateFolder); var schema = new Dictionary <string, object> { ["type"] = "object", ["title"] = "testmerger2", ["version"] = "1.0.0", ["$schema"] = "http://dotnet.github.io/docfx/schemas/v1.0/schema.json#", ["properties"] = new Dictionary <string, object> { ["uid"] = new { contentType = "uid" }, ["summary"] = new { contentType = "markdown" }, ["reference"] = new { contentType = "markdown", reference = "file" }, ["href"] = new { contentType = "href" }, ["xref"] = new { contentType = "xref" }, } }; var schemaFile = CreateFile("template/schemas/testmerger2.schema.json", JsonUtility.Serialize(schema), _templateFolder); var inputFileName = "src/src.yml"; var inputFile = CreateFile(inputFileName, @"### YamlMime:testmerger2 uid: uid1 summary: ""*Hello* [self](src.yml)"" href: xref: uid1 reference: ../inc/inc.md ", _inputFolder); var includeFile = CreateFile("inc/inc.md", @"[parent](../src/src.yml)", _inputFolder); var includeFile2 = CreateFile("inc/inc2.md", @"[overwrite](../src/src.yml)", _inputFolder); var overwriteFile = CreateFile("overwrite/a.md", $@"--- uid: uid1 summary: *content href: ../src/src.yml xref: uid1 reference: ../inc/inc2.md --- Nice ", _inputFolder); FileCollection files = new FileCollection(_defaultFiles); files.Add(DocumentType.Article, new[] { inputFile }, _inputFolder); files.Add(DocumentType.Overwrite, new[] { overwriteFile }, _inputFolder); BuildDocument(files); // One plugin warning for yml and one plugin warning for overwrite file Assert.True(listener.Items.Count == 0, listener.Items.Select(s => s.Message).ToDelimitedString()); var rawModelFilePath = GetRawModelFilePath(inputFileName); Assert.True(File.Exists(rawModelFilePath)); var rawModel = JsonUtility.Deserialize <JObject>(rawModelFilePath); Assert.Equal("Hello world!", rawModel["meta"].Value <string>()); Assert.Equal($"<p sourcefile=\"{overwriteFile}\" sourcestartlinenumber=\"8\" sourceendlinenumber=\"8\">Nice</p>\n", rawModel["summary"].Value <string>()); Assert.Equal("src.html", rawModel["href"].Value <string>()); Assert.Equal("uid1", rawModel["xref"].Value <string>()); Assert.Equal($"<p sourcefile=\"{includeFile2}\" sourcestartlinenumber=\"1\" sourceendlinenumber=\"1\"><a href=\"~/{inputFile}\" data-raw-source=\"[overwrite](../src/src.yml)\" sourcefile=\"{includeFile2}\" sourcestartlinenumber=\"1\" sourceendlinenumber=\"1\">overwrite</a></p>\n", rawModel["reference"].Value <string>()); var outputFile = GetOutputFilePath(inputFileName); Assert.Equal("<a class=\"xref\" href=\"src.html\">uid1</a>", File.ReadAllText(outputFile)); } }