From 801caee1d8a524b370446ab5eb1d66266433149d Mon Sep 17 00:00:00 2001 From: Richard Perry Date: Tue, 8 Oct 2024 22:05:11 +0100 Subject: [PATCH] Refactor URI construction and enhance test coverage (#126) * Refactor URI construction and enhance test coverage Refactored `DeleteOperation` and `ReplaceOperation` to directly include `operation.ItemId` in URI construction via `MakeAbsoluteUri`. Updated `ExecutableOperation` to support an optional `itemId` parameter in `MakeAbsoluteUri`. Added `MakeAbsoluteUri_WorksWithId` theory test to validate various URI construction scenarios. * Refactor URI handling and update related tests Modified `MakeAbsoluteUri` in `ExecutableOperation.cs` to handle `itemId` more robustly by conditionally formatting it with a leading slash if it is not empty and avoiding trailing slashes before `itemId`. Updated test cases in `OfflineDbContext_Tests.cs`, `AddOperation_Tests.cs`, and `ExecutableOperation_Tests.cs` to reflect the new URI formatting rules, specifically removing trailing slashes before query parameters in the expected URIs. --------- Co-authored-by: Adrian Hall --- .../Offline/Operations/DeleteOperation.cs | 4 +- .../Offline/Operations/ExecutableOperation.cs | 9 ++- .../Offline/Operations/ReplaceOperation.cs | 4 +- .../Offline/OfflineDbContext_Tests.cs | 74 +++++++++---------- .../Offline/Operations/AddOperation_Tests.cs | 2 +- .../Operations/ExecutableOperation_Tests.cs | 51 ++++++++++--- 6 files changed, 89 insertions(+), 55 deletions(-) diff --git a/src/CommunityToolkit.Datasync.Client/Offline/Operations/DeleteOperation.cs b/src/CommunityToolkit.Datasync.Client/Offline/Operations/DeleteOperation.cs index f1dd2bf..b7b48c1 100644 --- a/src/CommunityToolkit.Datasync.Client/Offline/Operations/DeleteOperation.cs +++ b/src/CommunityToolkit.Datasync.Client/Offline/Operations/DeleteOperation.cs @@ -21,8 +21,8 @@ internal class DeleteOperation(DatasyncOperation operation) : ExecutableOperatio /// The result of the push operation (async). internal override async Task ExecuteAsync(EntityDatasyncOptions options, CancellationToken cancellationToken = default) { - Uri endpoint = MakeAbsoluteUri(options.HttpClient.BaseAddress, options.Endpoint); - using HttpRequestMessage request = new(HttpMethod.Delete, new Uri(endpoint, operation.ItemId)); + Uri endpoint = MakeAbsoluteUri(options.HttpClient.BaseAddress, options.Endpoint, operation.ItemId); + using HttpRequestMessage request = new(HttpMethod.Delete, endpoint); if (!string.IsNullOrEmpty(operation.EntityVersion)) { request.Headers.IfMatch.Add(new EntityTagHeaderValue($"\"{operation.EntityVersion}\"")); diff --git a/src/CommunityToolkit.Datasync.Client/Offline/Operations/ExecutableOperation.cs b/src/CommunityToolkit.Datasync.Client/Offline/Operations/ExecutableOperation.cs index f67a989..27811a0 100644 --- a/src/CommunityToolkit.Datasync.Client/Offline/Operations/ExecutableOperation.cs +++ b/src/CommunityToolkit.Datasync.Client/Offline/Operations/ExecutableOperation.cs @@ -22,19 +22,22 @@ internal abstract class ExecutableOperation /// /// The base address from the client. /// A relative or absolute URI + /// The id of the item to append to the URI. /// - internal static Uri MakeAbsoluteUri(Uri? baseAddress, Uri relativeOrAbsoluteUri) + internal static Uri MakeAbsoluteUri(Uri? baseAddress, Uri relativeOrAbsoluteUri, string? itemId = null) { + itemId = string.IsNullOrWhiteSpace(itemId) ? string.Empty : $"/{itemId}"; + if (relativeOrAbsoluteUri.IsAbsoluteUri) { - return new Uri($"{relativeOrAbsoluteUri.ToString().TrimEnd('/')}/"); + return new Uri($"{relativeOrAbsoluteUri.ToString().TrimEnd('/')}{itemId}"); } if (baseAddress != null) { if (baseAddress.IsAbsoluteUri) { - return new Uri($"{new Uri(baseAddress, relativeOrAbsoluteUri).ToString().TrimEnd('/')}/"); + return new Uri($"{new Uri(baseAddress, relativeOrAbsoluteUri).ToString().TrimEnd('/')}{itemId}"); } } diff --git a/src/CommunityToolkit.Datasync.Client/Offline/Operations/ReplaceOperation.cs b/src/CommunityToolkit.Datasync.Client/Offline/Operations/ReplaceOperation.cs index ec69c17..42d1d60 100644 --- a/src/CommunityToolkit.Datasync.Client/Offline/Operations/ReplaceOperation.cs +++ b/src/CommunityToolkit.Datasync.Client/Offline/Operations/ReplaceOperation.cs @@ -21,8 +21,8 @@ internal class ReplaceOperation(DatasyncOperation operation) : ExecutableOperati /// The result of the push operation (async). internal override async Task ExecuteAsync(EntityDatasyncOptions options, CancellationToken cancellationToken = default) { - Uri endpoint = MakeAbsoluteUri(options.HttpClient.BaseAddress, options.Endpoint); - using HttpRequestMessage request = new(HttpMethod.Put, new Uri(endpoint, operation.ItemId)) + Uri endpoint = MakeAbsoluteUri(options.HttpClient.BaseAddress, options.Endpoint, operation.ItemId); + using HttpRequestMessage request = new(HttpMethod.Put, endpoint) { Content = new StringContent(operation.Item, JsonMediaType) }; diff --git a/tests/CommunityToolkit.Datasync.Client.Test/Offline/OfflineDbContext_Tests.cs b/tests/CommunityToolkit.Datasync.Client.Test/Offline/OfflineDbContext_Tests.cs index 9876b51..16e16ad 100644 --- a/tests/CommunityToolkit.Datasync.Client.Test/Offline/OfflineDbContext_Tests.cs +++ b/tests/CommunityToolkit.Datasync.Client.Test/Offline/OfflineDbContext_Tests.cs @@ -67,10 +67,10 @@ public async Task PullAsync_List_Works_InitialSync() actual.Should().BeEquivalentTo(expected); this.context.Handler.Requests.Should().HaveCount(4); - this.context.Handler.Requests[0].RequestUri.ToString().Should().Be("https://test.zumo.net/tables/movies/?$orderby=updatedAt&$count=true&__includedeleted=true"); - this.context.Handler.Requests[1].RequestUri.ToString().Should().Be("https://test.zumo.net/tables/movies/?$skip=5"); - this.context.Handler.Requests[2].RequestUri.ToString().Should().Be("https://test.zumo.net/tables/movies/?$skip=10"); - this.context.Handler.Requests[3].RequestUri.ToString().Should().Be("https://test.zumo.net/tables/movies/?$skip=15"); + this.context.Handler.Requests[0].RequestUri.ToString().Should().Be("https://test.zumo.net/tables/movies?$orderby=updatedAt&$count=true&__includedeleted=true"); + this.context.Handler.Requests[1].RequestUri.ToString().Should().Be("https://test.zumo.net/tables/movies?$skip=5"); + this.context.Handler.Requests[2].RequestUri.ToString().Should().Be("https://test.zumo.net/tables/movies?$skip=10"); + this.context.Handler.Requests[3].RequestUri.ToString().Should().Be("https://test.zumo.net/tables/movies?$skip=15"); DatasyncDeltaToken token = this.context.DatasyncDeltaTokens.Find(["CommunityToolkit.Datasync.TestCommon.Databases.ClientMovie"]); token.Should().NotBeNull(); @@ -103,10 +103,10 @@ public async Task PullAsync_DbSet_Works_InitialSync() actual.Should().BeEquivalentTo(expected); this.context.Handler.Requests.Should().HaveCount(4); - this.context.Handler.Requests[0].RequestUri.ToString().Should().Be("https://test.zumo.net/tables/movies/?$orderby=updatedAt&$count=true&__includedeleted=true"); - this.context.Handler.Requests[1].RequestUri.ToString().Should().Be("https://test.zumo.net/tables/movies/?$skip=5"); - this.context.Handler.Requests[2].RequestUri.ToString().Should().Be("https://test.zumo.net/tables/movies/?$skip=10"); - this.context.Handler.Requests[3].RequestUri.ToString().Should().Be("https://test.zumo.net/tables/movies/?$skip=15"); + this.context.Handler.Requests[0].RequestUri.ToString().Should().Be("https://test.zumo.net/tables/movies?$orderby=updatedAt&$count=true&__includedeleted=true"); + this.context.Handler.Requests[1].RequestUri.ToString().Should().Be("https://test.zumo.net/tables/movies?$skip=5"); + this.context.Handler.Requests[2].RequestUri.ToString().Should().Be("https://test.zumo.net/tables/movies?$skip=10"); + this.context.Handler.Requests[3].RequestUri.ToString().Should().Be("https://test.zumo.net/tables/movies?$skip=15"); DatasyncDeltaToken token = this.context.DatasyncDeltaTokens.Find(["CommunityToolkit.Datasync.TestCommon.Databases.ClientMovie"]); token.Should().NotBeNull(); @@ -147,10 +147,10 @@ public async Task PullAsync_Configurator_Works_InitialSync_Ver1() actual.Should().BeEquivalentTo(expected); this.context.Handler.Requests.Should().HaveCount(4); - this.context.Handler.Requests[0].RequestUri.ToString().Should().Be("https://test.zumo.net/tables/movies/?$filter=startswith%28title%2C%27abc%27%29&$orderby=updatedAt&$count=true&__includedeleted=true"); - this.context.Handler.Requests[1].RequestUri.ToString().Should().Be("https://test.zumo.net/tables/movies/?$skip=5"); - this.context.Handler.Requests[2].RequestUri.ToString().Should().Be("https://test.zumo.net/tables/movies/?$skip=10"); - this.context.Handler.Requests[3].RequestUri.ToString().Should().Be("https://test.zumo.net/tables/movies/?$skip=15"); + this.context.Handler.Requests[0].RequestUri.ToString().Should().Be("https://test.zumo.net/tables/movies?$filter=startswith%28title%2C%27abc%27%29&$orderby=updatedAt&$count=true&__includedeleted=true"); + this.context.Handler.Requests[1].RequestUri.ToString().Should().Be("https://test.zumo.net/tables/movies?$skip=5"); + this.context.Handler.Requests[2].RequestUri.ToString().Should().Be("https://test.zumo.net/tables/movies?$skip=10"); + this.context.Handler.Requests[3].RequestUri.ToString().Should().Be("https://test.zumo.net/tables/movies?$skip=15"); DatasyncDeltaToken token = this.context.DatasyncDeltaTokens.Find(["q-CommunityToolkit.Datasync.TestCommon.Databases.ClientMovie-abc"]); token.Should().NotBeNull(); @@ -191,10 +191,10 @@ public async Task PullAsync_Configurator_Works_InitialSync_Ver2() actual.Should().BeEquivalentTo(expected); this.context.Handler.Requests.Should().HaveCount(4); - this.context.Handler.Requests[0].RequestUri.ToString().Should().Be("https://test.zumo.net/tables/movies/?$filter=startswith%28title%2C%27abc%27%29&$orderby=updatedAt&$count=true&__includedeleted=true"); - this.context.Handler.Requests[1].RequestUri.ToString().Should().Be("https://test.zumo.net/tables/movies/?$skip=5"); - this.context.Handler.Requests[2].RequestUri.ToString().Should().Be("https://test.zumo.net/tables/movies/?$skip=10"); - this.context.Handler.Requests[3].RequestUri.ToString().Should().Be("https://test.zumo.net/tables/movies/?$skip=15"); + this.context.Handler.Requests[0].RequestUri.ToString().Should().Be("https://test.zumo.net/tables/movies?$filter=startswith%28title%2C%27abc%27%29&$orderby=updatedAt&$count=true&__includedeleted=true"); + this.context.Handler.Requests[1].RequestUri.ToString().Should().Be("https://test.zumo.net/tables/movies?$skip=5"); + this.context.Handler.Requests[2].RequestUri.ToString().Should().Be("https://test.zumo.net/tables/movies?$skip=10"); + this.context.Handler.Requests[3].RequestUri.ToString().Should().Be("https://test.zumo.net/tables/movies?$skip=15"); DatasyncDeltaToken token = this.context.DatasyncDeltaTokens.Find(["q-CommunityToolkit.Datasync.TestCommon.Databases.ClientMovie-a87ec01f71a5577199797b433e3bcc6b"]); token.Should().NotBeNull(); @@ -242,10 +242,10 @@ public async Task PullAsync_Configurator_Works_InitialSync_Ver3() actual.Should().BeEquivalentTo(expected); this.context.Handler.Requests.Should().HaveCount(4); - this.context.Handler.Requests[0].RequestUri.ToString().Should().Be("https://test.zumo.net/tables/movies/?$filter=startswith%28title%2C%27abc%27%29&$orderby=updatedAt&$count=true&__includedeleted=true"); - this.context.Handler.Requests[1].RequestUri.ToString().Should().Be("https://test.zumo.net/tables/movies/?$skip=5"); - this.context.Handler.Requests[2].RequestUri.ToString().Should().Be("https://test.zumo.net/tables/movies/?$skip=10"); - this.context.Handler.Requests[3].RequestUri.ToString().Should().Be("https://test.zumo.net/tables/movies/?$skip=15"); + this.context.Handler.Requests[0].RequestUri.ToString().Should().Be("https://test.zumo.net/tables/movies?$filter=startswith%28title%2C%27abc%27%29&$orderby=updatedAt&$count=true&__includedeleted=true"); + this.context.Handler.Requests[1].RequestUri.ToString().Should().Be("https://test.zumo.net/tables/movies?$skip=5"); + this.context.Handler.Requests[2].RequestUri.ToString().Should().Be("https://test.zumo.net/tables/movies?$skip=10"); + this.context.Handler.Requests[3].RequestUri.ToString().Should().Be("https://test.zumo.net/tables/movies?$skip=15"); DatasyncDeltaToken token = this.context.DatasyncDeltaTokens.Find(["q-CommunityToolkit.Datasync.TestCommon.Databases.ClientMovie-a87ec01f71a5577199797b433e3bcc6b"]); token.Should().NotBeNull(); @@ -281,10 +281,10 @@ public async Task PullAsync_Configurator_Works_InitialSync_Ver4() actual.Should().BeEquivalentTo(expected); this.context.Handler.Requests.Should().HaveCount(4); - this.context.Handler.Requests[0].RequestUri.ToString().Should().Be("https://test.zumo.net/tables/movies/?$orderby=updatedAt&$count=true&__includedeleted=true"); - this.context.Handler.Requests[1].RequestUri.ToString().Should().Be("https://test.zumo.net/tables/movies/?$skip=5"); - this.context.Handler.Requests[2].RequestUri.ToString().Should().Be("https://test.zumo.net/tables/movies/?$skip=10"); - this.context.Handler.Requests[3].RequestUri.ToString().Should().Be("https://test.zumo.net/tables/movies/?$skip=15"); + this.context.Handler.Requests[0].RequestUri.ToString().Should().Be("https://test.zumo.net/tables/movies?$orderby=updatedAt&$count=true&__includedeleted=true"); + this.context.Handler.Requests[1].RequestUri.ToString().Should().Be("https://test.zumo.net/tables/movies?$skip=5"); + this.context.Handler.Requests[2].RequestUri.ToString().Should().Be("https://test.zumo.net/tables/movies?$skip=10"); + this.context.Handler.Requests[3].RequestUri.ToString().Should().Be("https://test.zumo.net/tables/movies?$skip=15"); DatasyncDeltaToken token = this.context.DatasyncDeltaTokens.Find(["CommunityToolkit.Datasync.TestCommon.Databases.ClientMovie"]); token.Should().NotBeNull(); @@ -321,10 +321,10 @@ public async Task PullAsync_List_Works_FollowonSync() actual.Should().BeEquivalentTo(expected); this.context.Handler.Requests.Should().HaveCount(4); - this.context.Handler.Requests[0].RequestUri.ToString().Should().Be("https://test.zumo.net/tables/movies/?$filter=%28updatedAt gt cast%282024-08-23T20%3A22%3A54.291Z%2CEdm.DateTimeOffset%29%29&$orderby=updatedAt&$count=true&__includedeleted=true"); - this.context.Handler.Requests[1].RequestUri.ToString().Should().Be("https://test.zumo.net/tables/movies/?$skip=5"); - this.context.Handler.Requests[2].RequestUri.ToString().Should().Be("https://test.zumo.net/tables/movies/?$skip=10"); - this.context.Handler.Requests[3].RequestUri.ToString().Should().Be("https://test.zumo.net/tables/movies/?$skip=15"); + this.context.Handler.Requests[0].RequestUri.ToString().Should().Be("https://test.zumo.net/tables/movies?$filter=%28updatedAt gt cast%282024-08-23T20%3A22%3A54.291Z%2CEdm.DateTimeOffset%29%29&$orderby=updatedAt&$count=true&__includedeleted=true"); + this.context.Handler.Requests[1].RequestUri.ToString().Should().Be("https://test.zumo.net/tables/movies?$skip=5"); + this.context.Handler.Requests[2].RequestUri.ToString().Should().Be("https://test.zumo.net/tables/movies?$skip=10"); + this.context.Handler.Requests[3].RequestUri.ToString().Should().Be("https://test.zumo.net/tables/movies?$skip=15"); } [Fact] @@ -362,10 +362,10 @@ public async Task PullAsync_List_Works_DoesntAddDeletions() actual.Should().BeEquivalentTo(expected); this.context.Handler.Requests.Should().HaveCount(4); - this.context.Handler.Requests[0].RequestUri.ToString().Should().Be("https://test.zumo.net/tables/movies/?$filter=%28updatedAt gt cast%282024-08-23T20%3A22%3A54.291Z%2CEdm.DateTimeOffset%29%29&$orderby=updatedAt&$count=true&__includedeleted=true"); - this.context.Handler.Requests[1].RequestUri.ToString().Should().Be("https://test.zumo.net/tables/movies/?$skip=5"); - this.context.Handler.Requests[2].RequestUri.ToString().Should().Be("https://test.zumo.net/tables/movies/?$skip=10"); - this.context.Handler.Requests[3].RequestUri.ToString().Should().Be("https://test.zumo.net/tables/movies/?$skip=15"); + this.context.Handler.Requests[0].RequestUri.ToString().Should().Be("https://test.zumo.net/tables/movies?$filter=%28updatedAt gt cast%282024-08-23T20%3A22%3A54.291Z%2CEdm.DateTimeOffset%29%29&$orderby=updatedAt&$count=true&__includedeleted=true"); + this.context.Handler.Requests[1].RequestUri.ToString().Should().Be("https://test.zumo.net/tables/movies?$skip=5"); + this.context.Handler.Requests[2].RequestUri.ToString().Should().Be("https://test.zumo.net/tables/movies?$skip=10"); + this.context.Handler.Requests[3].RequestUri.ToString().Should().Be("https://test.zumo.net/tables/movies?$skip=15"); } [Fact] @@ -410,10 +410,10 @@ public async Task PullAsync_List_Works_DeletionsAndReplacements() actual.Should().BeEquivalentTo(expected); this.context.Handler.Requests.Should().HaveCount(4); - this.context.Handler.Requests[0].RequestUri.ToString().Should().Be("https://test.zumo.net/tables/movies/?$orderby=updatedAt&$count=true&__includedeleted=true"); - this.context.Handler.Requests[1].RequestUri.ToString().Should().Be("https://test.zumo.net/tables/movies/?$skip=5"); - this.context.Handler.Requests[2].RequestUri.ToString().Should().Be("https://test.zumo.net/tables/movies/?$skip=10"); - this.context.Handler.Requests[3].RequestUri.ToString().Should().Be("https://test.zumo.net/tables/movies/?$skip=15"); + this.context.Handler.Requests[0].RequestUri.ToString().Should().Be("https://test.zumo.net/tables/movies?$orderby=updatedAt&$count=true&__includedeleted=true"); + this.context.Handler.Requests[1].RequestUri.ToString().Should().Be("https://test.zumo.net/tables/movies?$skip=5"); + this.context.Handler.Requests[2].RequestUri.ToString().Should().Be("https://test.zumo.net/tables/movies?$skip=10"); + this.context.Handler.Requests[3].RequestUri.ToString().Should().Be("https://test.zumo.net/tables/movies?$skip=15"); } [Fact] @@ -426,7 +426,7 @@ public async Task PullAsync_List_FailedRequest() pullResult.IsSuccessful.Should().BeFalse(); pullResult.FailedRequests.Should().HaveCount(1); KeyValuePair kv = pullResult.FailedRequests.Single(); - kv.Key.Should().Be("https://test.zumo.net/tables/movies/?$orderby=updatedAt&$count=true&__includedeleted=true"); + kv.Key.Should().Be("https://test.zumo.net/tables/movies?$orderby=updatedAt&$count=true&__includedeleted=true"); } [Fact] diff --git a/tests/CommunityToolkit.Datasync.Client.Test/Offline/Operations/AddOperation_Tests.cs b/tests/CommunityToolkit.Datasync.Client.Test/Offline/Operations/AddOperation_Tests.cs index e5512b9..ba125de 100644 --- a/tests/CommunityToolkit.Datasync.Client.Test/Offline/Operations/AddOperation_Tests.cs +++ b/tests/CommunityToolkit.Datasync.Client.Test/Offline/Operations/AddOperation_Tests.cs @@ -53,7 +53,7 @@ public async Task AddOperation_ExecuteAsync() HttpRequestMessage request = handler.Requests.SingleOrDefault(); request.Should().NotBeNull(); request.Method.Should().Be(HttpMethod.Post); - request.RequestUri.ToString().Should().Be("https://test.zumo.net/tables/movies/"); + request.RequestUri.ToString().Should().Be("https://test.zumo.net/tables/movies"); (await request.Content.ReadAsStringAsync()).Should().Be(itemJson); response.Should().NotBeNull(); diff --git a/tests/CommunityToolkit.Datasync.Client.Test/Offline/Operations/ExecutableOperation_Tests.cs b/tests/CommunityToolkit.Datasync.Client.Test/Offline/Operations/ExecutableOperation_Tests.cs index e54ff4a..954b896 100644 --- a/tests/CommunityToolkit.Datasync.Client.Test/Offline/Operations/ExecutableOperation_Tests.cs +++ b/tests/CommunityToolkit.Datasync.Client.Test/Offline/Operations/ExecutableOperation_Tests.cs @@ -31,16 +31,16 @@ public async Task CreateAsync_InvalidKind() } [Theory] - [InlineData(null, "https://test.zumo.com/tables/movies", "https://test.zumo.com/tables/movies/")] - [InlineData(null, "https://test.zumo.com/tables/movies/", "https://test.zumo.com/tables/movies/")] - [InlineData("https://test.zumo.com", "/tables/movies", "https://test.zumo.com/tables/movies/")] - [InlineData("https://test.zumo.com", "/tables/movies/", "https://test.zumo.com/tables/movies/")] - [InlineData("https://test.zumo.com/", "/tables/movies", "https://test.zumo.com/tables/movies/")] - [InlineData("https://test.zumo.com/", "/tables/movies/", "https://test.zumo.com/tables/movies/")] - [InlineData("https://test.zumo.com/tables", "movies", "https://test.zumo.com/movies/")] - [InlineData("https://test.zumo.com/tables", "movies/", "https://test.zumo.com/movies/")] - [InlineData("https://test.zumo.com/tables", "/api/movies", "https://test.zumo.com/api/movies/")] - [InlineData("https://test.zumo.com/tables", "/api/movies/", "https://test.zumo.com/api/movies/")] + [InlineData(null, "https://test.zumo.com/tables/movies", "https://test.zumo.com/tables/movies")] + [InlineData(null, "https://test.zumo.com/tables/movies/", "https://test.zumo.com/tables/movies")] + [InlineData("https://test.zumo.com", "/tables/movies", "https://test.zumo.com/tables/movies")] + [InlineData("https://test.zumo.com", "/tables/movies/", "https://test.zumo.com/tables/movies")] + [InlineData("https://test.zumo.com/", "/tables/movies", "https://test.zumo.com/tables/movies")] + [InlineData("https://test.zumo.com/", "/tables/movies/", "https://test.zumo.com/tables/movies")] + [InlineData("https://test.zumo.com/tables", "movies", "https://test.zumo.com/movies")] + [InlineData("https://test.zumo.com/tables", "movies/", "https://test.zumo.com/movies")] + [InlineData("https://test.zumo.com/tables", "/api/movies", "https://test.zumo.com/api/movies")] + [InlineData("https://test.zumo.com/tables", "/api/movies/", "https://test.zumo.com/api/movies")] public void MakeAbsoluteUri_Works(string ba, string bb, string expected) { Uri arg1 = string.IsNullOrEmpty(ba) ? null : new Uri(ba, UriKind.Absolute); @@ -50,6 +50,37 @@ public void MakeAbsoluteUri_Works(string ba, string bb, string expected) actual.ToString().Should().Be(expected); } + + [Theory] + [InlineData(null, "https://test.zumo.com/tables/movies", "123", "https://test.zumo.com/tables/movies/123")] + [InlineData(null, "https://test.zumo.com/tables/movies/", "123", "https://test.zumo.com/tables/movies/123")] + [InlineData("https://test.zumo.com", "/tables/movies", "123", "https://test.zumo.com/tables/movies/123")] + [InlineData("https://test.zumo.com", "/tables/movies/", "123", "https://test.zumo.com/tables/movies/123")] + [InlineData("https://test.zumo.com/", "/tables/movies", "123", "https://test.zumo.com/tables/movies/123")] + [InlineData("https://test.zumo.com/", "/tables/movies/", "123", "https://test.zumo.com/tables/movies/123")] + [InlineData("https://test.zumo.com/tables", "movies", "123", "https://test.zumo.com/movies/123")] + [InlineData("https://test.zumo.com/tables", "movies/", "123", "https://test.zumo.com/movies/123")] + [InlineData("https://test.zumo.com/tables", "/api/movies", "123", "https://test.zumo.com/api/movies/123")] + [InlineData("https://test.zumo.com/tables", "/api/movies/", "123", "https://test.zumo.com/api/movies/123")] + [InlineData(null, "https://test.zumo.com/tables/movies", "E0B4E855-4C95-4E9F-8859-581CABB4B66F:5BE95902-65E3-4A21-97B8-D38F36331E8D", "https://test.zumo.com/tables/movies/E0B4E855-4C95-4E9F-8859-581CABB4B66F:5BE95902-65E3-4A21-97B8-D38F36331E8D")] + [InlineData(null, "https://test.zumo.com/tables/movies/", "E0B4E855-4C95-4E9F-8859-581CABB4B66F:5BE95902-65E3-4A21-97B8-D38F36331E8D", "https://test.zumo.com/tables/movies/E0B4E855-4C95-4E9F-8859-581CABB4B66F:5BE95902-65E3-4A21-97B8-D38F36331E8D")] + [InlineData("https://test.zumo.com", "/tables/movies", "E0B4E855-4C95-4E9F-8859-581CABB4B66F:5BE95902-65E3-4A21-97B8-D38F36331E8D", "https://test.zumo.com/tables/movies/E0B4E855-4C95-4E9F-8859-581CABB4B66F:5BE95902-65E3-4A21-97B8-D38F36331E8D")] + [InlineData("https://test.zumo.com", "/tables/movies/", "E0B4E855-4C95-4E9F-8859-581CABB4B66F:5BE95902-65E3-4A21-97B8-D38F36331E8D", "https://test.zumo.com/tables/movies/E0B4E855-4C95-4E9F-8859-581CABB4B66F:5BE95902-65E3-4A21-97B8-D38F36331E8D")] + [InlineData("https://test.zumo.com/", "/tables/movies", "E0B4E855-4C95-4E9F-8859-581CABB4B66F:5BE95902-65E3-4A21-97B8-D38F36331E8D", "https://test.zumo.com/tables/movies/E0B4E855-4C95-4E9F-8859-581CABB4B66F:5BE95902-65E3-4A21-97B8-D38F36331E8D")] + [InlineData("https://test.zumo.com/", "/tables/movies/", "E0B4E855-4C95-4E9F-8859-581CABB4B66F:5BE95902-65E3-4A21-97B8-D38F36331E8D", "https://test.zumo.com/tables/movies/E0B4E855-4C95-4E9F-8859-581CABB4B66F:5BE95902-65E3-4A21-97B8-D38F36331E8D")] + [InlineData("https://test.zumo.com/tables", "movies", "E0B4E855-4C95-4E9F-8859-581CABB4B66F:5BE95902-65E3-4A21-97B8-D38F36331E8D", "https://test.zumo.com/movies/E0B4E855-4C95-4E9F-8859-581CABB4B66F:5BE95902-65E3-4A21-97B8-D38F36331E8D")] + [InlineData("https://test.zumo.com/tables", "movies/", "E0B4E855-4C95-4E9F-8859-581CABB4B66F:5BE95902-65E3-4A21-97B8-D38F36331E8D", "https://test.zumo.com/movies/E0B4E855-4C95-4E9F-8859-581CABB4B66F:5BE95902-65E3-4A21-97B8-D38F36331E8D")] + [InlineData("https://test.zumo.com/tables", "/api/movies", "E0B4E855-4C95-4E9F-8859-581CABB4B66F:5BE95902-65E3-4A21-97B8-D38F36331E8D", "https://test.zumo.com/api/movies/E0B4E855-4C95-4E9F-8859-581CABB4B66F:5BE95902-65E3-4A21-97B8-D38F36331E8D")] + [InlineData("https://test.zumo.com/tables", "/api/movies/", "E0B4E855-4C95-4E9F-8859-581CABB4B66F:5BE95902-65E3-4A21-97B8-D38F36331E8D", "https://test.zumo.com/api/movies/E0B4E855-4C95-4E9F-8859-581CABB4B66F:5BE95902-65E3-4A21-97B8-D38F36331E8D")] + public void MakeAbsoluteUri_WorksWithId(string ba, string bb, string itemId, string expected) + { + Uri arg1 = string.IsNullOrEmpty(ba) ? null : new Uri(ba, UriKind.Absolute); + Uri arg2 = bb.StartsWith("http") ? new Uri(bb, UriKind.Absolute) : new Uri(bb, UriKind.Relative); + Uri actual = ExecutableOperation.MakeAbsoluteUri(arg1, arg2, itemId); + + actual.ToString().Should().Be(expected); + } + [Fact] public void MakeAbsoluteUri_BaseAddressRelative() {