diff --git a/tests/Kiota.Builder.Tests/Extensions/StringExtensionsTests.cs b/tests/Kiota.Builder.Tests/Extensions/StringExtensionsTests.cs index 6e9fce63a3..ebc156cf70 100644 --- a/tests/Kiota.Builder.Tests/Extensions/StringExtensionsTests.cs +++ b/tests/Kiota.Builder.Tests/Extensions/StringExtensionsTests.cs @@ -85,7 +85,7 @@ public void NormalizeNameSpaceName() Assert.Equal("Toto", "toto".NormalizeNameSpaceName("-")); Assert.Equal("Microsoft_Graph_Message_Content", "microsoft.Graph.Message.Content".NormalizeNameSpaceName("_")); } - [InlineData("\" !#$%&'()*+,./:;<=>?@[]\\^`{}|~-", "plus")] + [InlineData("\" !#$%&'()*+,./:;<=>?@[]^`{}|~-", "plus")] [InlineData("unchanged", "unchanged")] [InlineData("@odata.changed", "OdataChanged")] [InlineData("specialLast@", "specialLast")] @@ -98,6 +98,9 @@ public void NormalizeNameSpaceName() [InlineData("-1-", "minus_1")] [InlineData("-1-1", "minus_11")] [InlineData("-", "minus")] + [InlineData("\\", "Slash")] + [InlineData("Param\\", "ParamSlash")] + [InlineData("Param\\RequestBuilder", "ParamSlashRequestBuilder")] [Theory] public void CleansUpSymbolNames(string input, string expected) { diff --git a/tests/Kiota.Builder.Tests/OpenApiSampleFiles/TrailingSlashSampleYml.cs b/tests/Kiota.Builder.Tests/OpenApiSampleFiles/TrailingSlashSampleYml.cs new file mode 100644 index 0000000000..db58ed9047 --- /dev/null +++ b/tests/Kiota.Builder.Tests/OpenApiSampleFiles/TrailingSlashSampleYml.cs @@ -0,0 +1,132 @@ +namespace Kiota.Builder.Tests.OpenApiSampleFiles; + +public static class TrailingSlashSampleYml +{ + /** + * An OpenAPI 3.0.0 sample document with trailing slashes on some paths. + */ + public static readonly string OpenApiYaml = @" +openapi: 3.0.0 +info: + title: Sample API + description: A sample API that uses trailing slashes. + version: 1.0.0 +servers: + - url: https://api.example.com/v1 +paths: + /foo: + get: + summary: Get foo + description: Returns foo. + responses: + '200': + description: foo + content: + text/plain: + schema: + type: string + /foo/: + get: + summary: Get foo slash + description: Returns foo slash. + responses: + '200': + description: foo slash + content: + text/plain: + schema: + type: string + /message/{id}: + get: + summary: Get a Message + description: Returns a single Message object. + parameters: + - name: id + in: path + required: true + schema: + type: string + responses: + '200': + description: A Message object + content: + application/json: + schema: + $ref: '#/components/schemas/Message' + /message/{id}/: + get: + summary: Get replies to a Message + description: Returns a list of Message object replies for a Message. + parameters: + - name: id + in: path + required: true + schema: + type: string + responses: + '200': + description: A list of Message objects + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Message' + /bucket/{name}/: + get: + summary: List items in a bucket + description: Returns a list of BucketFiles in a bucket. + parameters: + - name: name + in: path + required: true + schema: + type: string + responses: + '200': + description: A list of BucketFile objects + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/BucketFile' + /bucket/{name}/{id}: + get: + summary: Get a bucket item + description: Returns a single BucketFile object. + parameters: + - name: name + in: path + required: true + schema: + type: string + - name: id + in: path + required: true + schema: + type: string + responses: + '200': + description: A BucketFile object + content: + application/json: + schema: + $ref: '#/components/schemas/BucketFile' +components: + schemas: + Message: + type: object + properties: + Guid: + type: string + required: + - Guid + BucketFile: + type: object + properties: + Guid: + type: string + required: + - Guid"; +} diff --git a/tests/Kiota.Builder.Tests/Refiners/TypeScriptLanguageRefinerTests.cs b/tests/Kiota.Builder.Tests/Refiners/TypeScriptLanguageRefinerTests.cs index 540f49f10d..7289ec93c1 100644 --- a/tests/Kiota.Builder.Tests/Refiners/TypeScriptLanguageRefinerTests.cs +++ b/tests/Kiota.Builder.Tests/Refiners/TypeScriptLanguageRefinerTests.cs @@ -961,6 +961,55 @@ public async Task ParsesAndRefinesUnionOfPrimitiveValuesAsync() var unionType = modelCodeFile.GetChildElements().Where(x => x is CodeFunction function && TypeScriptRefiner.GetOriginalComposedType(function.OriginalLocalMethod.ReturnType) is not null).ToList(); Assert.True(unionType.Count > 0); } + [Fact] + public async Task ParsesAndRefinesPathsWithTrailingSlashAsync() + { + var generationConfiguration = new GenerationConfiguration { Language = GenerationLanguage.TypeScript }; + var tempFilePath = Path.Combine(Path.GetTempPath(), Path.GetTempFileName()); + await File.WriteAllTextAsync(tempFilePath, TrailingSlashSampleYml.OpenApiYaml); + var mockLogger = new Mock>(); + var builder = new KiotaBuilder(mockLogger.Object, new GenerationConfiguration { ClientClassName = "Testing", Serializers = ["none"], Deserializers = ["none"] }, _httpClient); + await using var fs = new FileStream(tempFilePath, FileMode.Open); + var document = await builder.CreateOpenApiDocumentAsync(fs); + var node = builder.CreateUriSpace(document); + builder.SetApiRootUrl(); + var codeModel = builder.CreateSourceModel(node); + var rootNS = codeModel.FindNamespaceByName("ApiSdk"); + Assert.NotNull(rootNS); + await ILanguageRefiner.RefineAsync(generationConfiguration, rootNS); + Assert.NotNull(rootNS); + + var fooNS = rootNS.FindNamespaceByName("ApiSdk.foo"); + Assert.NotNull(fooNS); + var fooCodeFile = fooNS.FindChildByName("fooRequestBuilder", false); + Assert.NotNull(fooCodeFile); + var fooRequestBuilder = fooCodeFile.FindChildByName("fooRequestBuilder", false); + var fooSlashRequestBuilder = fooCodeFile.FindChildByName("fooSlashRequestBuilder", false); + Assert.NotNull(fooRequestBuilder); + Assert.NotNull(fooSlashRequestBuilder); + + var messageNS = rootNS.FindNamespaceByName("ApiSdk.message"); + Assert.NotNull(messageNS); + var messageCodeFile = messageNS.FindChildByName("messageRequestBuilder", false); + Assert.NotNull(messageCodeFile); + var messageRequestBuilder = messageCodeFile.FindChildByName("messageRequestBuilder", false); + Assert.NotNull(messageRequestBuilder); + var messageWithIdSlashMethod = messageRequestBuilder.FindChildByName("withIdSlash", false); + var messageByIdMethod = messageRequestBuilder.FindChildByName("byId", false); + Assert.NotNull(messageWithIdSlashMethod); + Assert.NotNull(messageByIdMethod); + + var bucketNS = rootNS.FindNamespaceByName("ApiSdk.bucket"); + Assert.NotNull(bucketNS); + var bucketItemNS = bucketNS.FindChildByName("ApiSdk.bucket.item", false); + Assert.NotNull(bucketItemNS); + var bucketItemCodeFile = bucketItemNS.FindChildByName("WithNameItemRequestBuilder", false); + Assert.NotNull(bucketItemCodeFile); + var bucketWithNameItemRequestBuilder = bucketItemCodeFile.FindChildByName("WithNameItemRequestBuilder", false); + var bucketWithNameSlashRequestBuilder = bucketItemCodeFile.FindChildByName("WithNameSlashRequestBuilder", false); + Assert.NotNull(bucketWithNameItemRequestBuilder); + Assert.NotNull(bucketWithNameSlashRequestBuilder); + } [Fact] public void GetOriginalComposedType_ReturnsNull_WhenElementIsNull() diff --git a/tests/Kiota.Builder.Tests/Writers/CSharp/CodeEnumWriterTests.cs b/tests/Kiota.Builder.Tests/Writers/CSharp/CodeEnumWriterTests.cs index 0a76a2e617..54732b0ed7 100644 --- a/tests/Kiota.Builder.Tests/Writers/CSharp/CodeEnumWriterTests.cs +++ b/tests/Kiota.Builder.Tests/Writers/CSharp/CodeEnumWriterTests.cs @@ -82,7 +82,7 @@ public void NamesDontDiffer_DoesntWriteEnumMember() } [Theory] - [InlineData("\\", "BackSlash")] + [InlineData("\\", "Slash")] [InlineData("?", "QuestionMark")] [InlineData("$", "Dollar")] [InlineData("~", "Tilde")] diff --git a/tests/Kiota.Builder.Tests/Writers/TypeScript/CodeConstantWriterTests.cs b/tests/Kiota.Builder.Tests/Writers/TypeScript/CodeConstantWriterTests.cs index 759ea67dc8..781b178b33 100644 --- a/tests/Kiota.Builder.Tests/Writers/TypeScript/CodeConstantWriterTests.cs +++ b/tests/Kiota.Builder.Tests/Writers/TypeScript/CodeConstantWriterTests.cs @@ -477,6 +477,33 @@ public void WritesRequestExecutorBody() Assert.Contains("403: createError403FromDiscriminatorValue as ParsableFactory", result); } [Fact] + public void WritesRequestsMetadataWithCorrectUriTemplate() + { + parentClass.Kind = CodeClassKind.RequestBuilder; + method.Kind = CodeMethodKind.RequestExecutor; + method.HttpMethod = HttpMethod.Get; + AddRequestProperties(); + AddRequestBodyParameters(); + var constant = CodeConstant.FromRequestBuilderToRequestsMetadata(parentClass); + var codeFile = root.TryAddCodeFile("foo", constant); + codeFile.AddElements(new CodeConstant + { + Name = "firstAndWrongUriTemplate", + Kind = CodeConstantKind.UriTemplate, + UriTemplate = "{+baseurl}/foo/" + }); + codeFile.AddElements(new CodeConstant + { + Name = "parentClassUriTemplate", + Kind = CodeConstantKind.UriTemplate, + UriTemplate = "{+baseurl}/foo" + }); + writer.Write(constant); + var result = tw.ToString(); + Assert.Contains("uriTemplate: ParentClassUriTemplate", result); + AssertExtensions.CurlyBracesAreClosed(result); + } + [Fact] public void WritesIndexer() { AddRequestProperties();