From 64a05e48c81e47d122ee54f79c33cafa310df843 Mon Sep 17 00:00:00 2001 From: Matthew Parker Date: Sat, 7 Dec 2024 09:54:24 +0000 Subject: [PATCH 01/22] Implemented List Documents --- .../Clients/DatabasesClient.cs | 18 +++++++++++++-- .../Clients/IDatabasesClient.cs | 13 +++++++---- .../Internals/IDatabasesApi.cs | 10 ++++----- src/PinguApps.Appwrite.Playground/App.cs | 22 ++++++++++++++----- .../Clients/DatabasesClient.cs | 17 ++++++++++++-- .../Clients/IDatabasesClient.cs | 11 +++++++--- 6 files changed, 69 insertions(+), 22 deletions(-) diff --git a/src/PinguApps.Appwrite.Client/Clients/DatabasesClient.cs b/src/PinguApps.Appwrite.Client/Clients/DatabasesClient.cs index 06f0cb89..aa5789cc 100644 --- a/src/PinguApps.Appwrite.Client/Clients/DatabasesClient.cs +++ b/src/PinguApps.Appwrite.Client/Clients/DatabasesClient.cs @@ -2,6 +2,7 @@ using System.Diagnostics.CodeAnalysis; using System.Threading.Tasks; using PinguApps.Appwrite.Client.Internals; +using PinguApps.Appwrite.Client.Utils; using PinguApps.Appwrite.Shared; using PinguApps.Appwrite.Shared.Requests.Databases; using PinguApps.Appwrite.Shared.Responses; @@ -18,9 +19,22 @@ internal DatabasesClient(IDatabasesApi databasesApi) _databasesApi = databasesApi; } - [ExcludeFromCodeCoverage] /// - public Task> ListDocuments(ListDocumentsRequest request) => throw new NotImplementedException(); + public async Task> ListDocuments(ListDocumentsRequest request) + { + try + { + request.Validate(true); + + var result = await _databasesApi.ListDocuments(GetCurrentSessionOrThrow(), request.DatabaseId, request.CollectionId, RequestUtils.GetQueryStrings(request.Queries)); + + return result.GetApiResponse(); + } + catch (Exception e) + { + return e.GetExceptionResponse(); + } + } [ExcludeFromCodeCoverage] /// diff --git a/src/PinguApps.Appwrite.Client/Clients/IDatabasesClient.cs b/src/PinguApps.Appwrite.Client/Clients/IDatabasesClient.cs index 9b337035..e2e4baee 100644 --- a/src/PinguApps.Appwrite.Client/Clients/IDatabasesClient.cs +++ b/src/PinguApps.Appwrite.Client/Clients/IDatabasesClient.cs @@ -11,10 +11,18 @@ namespace PinguApps.Appwrite.Client.Clients; /// All data returned by the Databases service are represented as structured JSON documents. /// The Databases service can contain multiple databases, each database can contain multiple collections. A collection is a group of similarly structured documents. The accepted structure of documents is defined by collection attributes. The collection attributes help you ensure all your user-submitted data is validated and stored according to the collection structure. /// Using Appwrite permissions architecture, you can assign read or write access to each collection or document in your project for either a specific user, team, user role, or even grant it with public access (any). You can learn more about how Appwrite handles permissions and access control. -/// Appwrite Docs +/// Appwrite Docs /// public interface IDatabasesClient { + /// + /// Get a list of all the user's documents in a given collection. You can use the query params to filter your results. + /// Appwrite Docs + /// + /// The request content + /// The documents list + Task> ListDocuments(ListDocumentsRequest request); + [Obsolete("Endpoint not yet implemented.")] Task> CreateDocument(CreateDocumentRequest request); @@ -24,9 +32,6 @@ public interface IDatabasesClient [Obsolete("Endpoint not yet implemented.")] Task> GetDocument(GetDocumentRequest request); - [Obsolete("Endpoint not yet implemented.")] - Task> ListDocuments(ListDocumentsRequest request); - [Obsolete("Endpoint not yet implemented.")] Task> UpdateDocument(UpdateDocumentRequest request); } diff --git a/src/PinguApps.Appwrite.Client/Internals/IDatabasesApi.cs b/src/PinguApps.Appwrite.Client/Internals/IDatabasesApi.cs index 408af82a..86d937eb 100644 --- a/src/PinguApps.Appwrite.Client/Internals/IDatabasesApi.cs +++ b/src/PinguApps.Appwrite.Client/Internals/IDatabasesApi.cs @@ -10,18 +10,18 @@ internal interface IDatabasesApi : IBaseApi { [Get("/databases/{databaseId}/collections/{collectionId}/documents")] [QueryUriFormat(UriFormat.Unescaped)] - Task> ListDocuments(string databaseId, string collectionId, [Query(CollectionFormat.Multi), AliasAs("queries[]")] IEnumerable queries); + Task> ListDocuments([Header("x-appwrite-session")] string session, string databaseId, string collectionId, [Query(CollectionFormat.Multi), AliasAs("queries[]")] IEnumerable queries); [Post("/databases/{databaseId}/collections/{collectionId}/documents")] - Task> CreateDocument(string databaseId, string collectionId, CreateDocumentRequest request); + Task> CreateDocument([Header("x-appwrite-session")] string session, string databaseId, string collectionId, CreateDocumentRequest request); [Delete("/databases/{databaseId}/collections/{collectionId}/documents/{documentId}")] - Task DeleteDocument(string databaseId, string collectionId, string documentId); + Task DeleteDocument([Header("x-appwrite-session")] string session, string databaseId, string collectionId, string documentId); [Get("/databases/{databaseId}/collections/{collectionId}/documents/{documentId}")] [QueryUriFormat(UriFormat.Unescaped)] - Task> GetDocument(string databaseId, string collectionId, string documentId, [Query(CollectionFormat.Multi), AliasAs("queries[]")] IEnumerable queries); + Task> GetDocument([Header("x-appwrite-session")] string session, string databaseId, string collectionId, string documentId, [Query(CollectionFormat.Multi), AliasAs("queries[]")] IEnumerable queries); [Patch("/databases/{databaseId}/collections/{collectionId}/documents/{documentId}")] - Task> UpdateDocument(string databaseId, string collectionId, string documentId, UpdateDocumentRequest request); + Task> UpdateDocument([Header("x-appwrite-session")] string session, string databaseId, string collectionId, string documentId, UpdateDocumentRequest request); } diff --git a/src/PinguApps.Appwrite.Playground/App.cs b/src/PinguApps.Appwrite.Playground/App.cs index 20e50e11..0bcff66c 100644 --- a/src/PinguApps.Appwrite.Playground/App.cs +++ b/src/PinguApps.Appwrite.Playground/App.cs @@ -17,16 +17,26 @@ public App(Client.IAppwriteClient client, Server.Clients.IAppwriteClient server, public async Task Run(string[] args) { - var request = new GetIndexRequest() + var request = new ListDocumentsRequest() { - DatabaseId = "6748b44d000b2b0e73ac", - CollectionId = "6748bb30002a12d4708f", - Key = "index_1" + DatabaseId = "67541a2800221703e717", + CollectionId = "67541a37001514b81821" }; - var response = await _server.Databases.GetIndex(request); + var serverResponse = await _server.Databases.ListDocuments(request); - Console.WriteLine(response.Result.Match( + Console.WriteLine(serverResponse.Result.Match( + result => result.ToString(), + appwriteError => appwriteError.Message, + internalError => internalError.Message)); + + Console.WriteLine("###############################################################################"); + + _client.SetSession(_session); + + var clientResponse = await _client.Databases.ListDocuments(request); + + Console.WriteLine(clientResponse.Result.Match( result => result.ToString(), appwriteError => appwriteError.Message, internalError => internalError.Message)); diff --git a/src/PinguApps.Appwrite.Server/Clients/DatabasesClient.cs b/src/PinguApps.Appwrite.Server/Clients/DatabasesClient.cs index 58df7c69..b0d92d1d 100644 --- a/src/PinguApps.Appwrite.Server/Clients/DatabasesClient.cs +++ b/src/PinguApps.Appwrite.Server/Clients/DatabasesClient.cs @@ -582,9 +582,22 @@ public async Task> UpdateRelationshipAttri } } - [ExcludeFromCodeCoverage] /// - public Task> ListDocuments(ListDocumentsRequest request) => throw new NotImplementedException(); + public async Task> ListDocuments(ListDocumentsRequest request) + { + try + { + request.Validate(true); + + var result = await _databasesApi.ListDocuments(request.DatabaseId, request.CollectionId, RequestUtils.GetQueryStrings(request.Queries)); + + return result.GetApiResponse(); + } + catch (Exception e) + { + return e.GetExceptionResponse(); + } + } [ExcludeFromCodeCoverage] /// diff --git a/src/PinguApps.Appwrite.Server/Clients/IDatabasesClient.cs b/src/PinguApps.Appwrite.Server/Clients/IDatabasesClient.cs index 2351eeec..fc689c8a 100644 --- a/src/PinguApps.Appwrite.Server/Clients/IDatabasesClient.cs +++ b/src/PinguApps.Appwrite.Server/Clients/IDatabasesClient.cs @@ -282,6 +282,14 @@ public interface IDatabasesClient /// The relationship attribute Task> UpdateRelationshipAttribute(UpdateRelationshipAttributeRequest request); + /// + /// Get a list of all the user's documents in a given collection. You can use the query params to filter your results. + /// Appwrite Docs + /// + /// The request content + /// The documents list + Task> ListDocuments(ListDocumentsRequest request); + [Obsolete("Endpoint not yet implemented.")] Task> CreateDocument(CreateDocumentRequest request); @@ -291,9 +299,6 @@ public interface IDatabasesClient [Obsolete("Endpoint not yet implemented.")] Task> GetDocument(GetDocumentRequest request); - [Obsolete("Endpoint not yet implemented.")] - Task> ListDocuments(ListDocumentsRequest request); - [Obsolete("Endpoint not yet implemented.")] Task> UpdateDocument(UpdateDocumentRequest request); From d79b5eecbbfd5944f40b6cb9affbd8b14b16f327 Mon Sep 17 00:00:00 2001 From: Matthew Parker Date: Sun, 8 Dec 2024 00:24:01 +0000 Subject: [PATCH 02/22] added server tests for list documents --- .../DatabasesClientTests.ListDocuments.cs | 99 +++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.ListDocuments.cs diff --git a/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.ListDocuments.cs b/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.ListDocuments.cs new file mode 100644 index 00000000..c7099d4f --- /dev/null +++ b/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.ListDocuments.cs @@ -0,0 +1,99 @@ +using System.Net; +using PinguApps.Appwrite.Shared.Requests.Databases; +using PinguApps.Appwrite.Shared.Tests; +using PinguApps.Appwrite.Shared.Utils; +using RichardSzalay.MockHttp; + +namespace PinguApps.Appwrite.Server.Tests.Clients.Databases; +public partial class DatabasesClientTests +{ + [Fact] + public async Task ListDocuments_ShouldReturnSuccess_WhenApiCallSucceeds() + { + // Arrange + var request = new ListDocumentsRequest + { + DatabaseId = IdUtils.GenerateUniqueId(), + CollectionId = IdUtils.GenerateUniqueId() + }; + + _mockHttp.Expect(HttpMethod.Get, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/documents") + .ExpectedHeaders() + .Respond(TestConstants.AppJson, TestConstants.DocumentsListResponse); + + // Act + var result = await _appwriteClient.Databases.ListDocuments(request); + + // Assert + Assert.True(result.Success); + } + + [Fact] + public async Task ListDocuments_ShouldProvideQueryParams_WhenQueriesProvided() + { + // Arrange + var query = Query.Limit(5); + var request = new ListDocumentsRequest + { + DatabaseId = IdUtils.GenerateUniqueId(), + CollectionId = IdUtils.GenerateUniqueId(), + Queries = [query] + }; + + _mockHttp.Expect(HttpMethod.Get, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/documents") + .ExpectedHeaders() + .WithQueryString($"queries[]={query.GetQueryString()}") + .Respond(TestConstants.AppJson, TestConstants.DocumentsListResponse); + + // Act + var result = await _appwriteClient.Databases.ListDocuments(request); + + // Assert + Assert.True(result.Success); + } + + [Fact] + public async Task ListDocuments_ShouldHandleException_WhenApiCallFails() + { + // Arrange + var request = new ListDocumentsRequest + { + DatabaseId = IdUtils.GenerateUniqueId(), + CollectionId = IdUtils.GenerateUniqueId() + }; + + _mockHttp.Expect(HttpMethod.Get, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/documents") + .ExpectedHeaders() + .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); + + // Act + var result = await _appwriteClient.Databases.ListDocuments(request); + + // Assert + Assert.True(result.IsError); + Assert.True(result.IsAppwriteError); + } + + [Fact] + public async Task ListDocuments_ShouldReturnErrorResponse_WhenExceptionOccurs() + { + // Arrange + var request = new ListDocumentsRequest + { + DatabaseId = IdUtils.GenerateUniqueId(), + CollectionId = IdUtils.GenerateUniqueId() + }; + + _mockHttp.Expect(HttpMethod.Get, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/documents") + .ExpectedHeaders() + .Throw(new HttpRequestException("An error occurred")); + + // Act + var result = await _appwriteClient.Databases.ListDocuments(request); + + // Assert + Assert.False(result.Success); + Assert.True(result.IsInternalError); + Assert.Equal("An error occurred", result.Result.AsT2.Message); + } +} From fe431be07f7d374afb256546b772f71e1bff7daa Mon Sep 17 00:00:00 2001 From: Matthew Parker Date: Sun, 8 Dec 2024 00:38:02 +0000 Subject: [PATCH 03/22] Ensured that client operations don't require a login, but will pass it when needed --- .../Clients/DatabasesClient.cs | 2 +- .../Internals/IDatabasesApi.cs | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/PinguApps.Appwrite.Client/Clients/DatabasesClient.cs b/src/PinguApps.Appwrite.Client/Clients/DatabasesClient.cs index aa5789cc..d1f3833b 100644 --- a/src/PinguApps.Appwrite.Client/Clients/DatabasesClient.cs +++ b/src/PinguApps.Appwrite.Client/Clients/DatabasesClient.cs @@ -26,7 +26,7 @@ public async Task> ListDocuments(ListDocumentsRequ { request.Validate(true); - var result = await _databasesApi.ListDocuments(GetCurrentSessionOrThrow(), request.DatabaseId, request.CollectionId, RequestUtils.GetQueryStrings(request.Queries)); + var result = await _databasesApi.ListDocuments(GetCurrentSession(), request.DatabaseId, request.CollectionId, RequestUtils.GetQueryStrings(request.Queries)); return result.GetApiResponse(); } diff --git a/src/PinguApps.Appwrite.Client/Internals/IDatabasesApi.cs b/src/PinguApps.Appwrite.Client/Internals/IDatabasesApi.cs index 86d937eb..cc723517 100644 --- a/src/PinguApps.Appwrite.Client/Internals/IDatabasesApi.cs +++ b/src/PinguApps.Appwrite.Client/Internals/IDatabasesApi.cs @@ -10,18 +10,18 @@ internal interface IDatabasesApi : IBaseApi { [Get("/databases/{databaseId}/collections/{collectionId}/documents")] [QueryUriFormat(UriFormat.Unescaped)] - Task> ListDocuments([Header("x-appwrite-session")] string session, string databaseId, string collectionId, [Query(CollectionFormat.Multi), AliasAs("queries[]")] IEnumerable queries); + Task> ListDocuments([Header("x-appwrite-session")] string? session, string databaseId, string collectionId, [Query(CollectionFormat.Multi), AliasAs("queries[]")] IEnumerable queries); [Post("/databases/{databaseId}/collections/{collectionId}/documents")] - Task> CreateDocument([Header("x-appwrite-session")] string session, string databaseId, string collectionId, CreateDocumentRequest request); + Task> CreateDocument([Header("x-appwrite-session")] string? session, string databaseId, string collectionId, CreateDocumentRequest request); [Delete("/databases/{databaseId}/collections/{collectionId}/documents/{documentId}")] - Task DeleteDocument([Header("x-appwrite-session")] string session, string databaseId, string collectionId, string documentId); + Task DeleteDocument([Header("x-appwrite-session")] string? session, string databaseId, string collectionId, string documentId); [Get("/databases/{databaseId}/collections/{collectionId}/documents/{documentId}")] [QueryUriFormat(UriFormat.Unescaped)] - Task> GetDocument([Header("x-appwrite-session")] string session, string databaseId, string collectionId, string documentId, [Query(CollectionFormat.Multi), AliasAs("queries[]")] IEnumerable queries); + Task> GetDocument([Header("x-appwrite-session")] string? session, string databaseId, string collectionId, string documentId, [Query(CollectionFormat.Multi), AliasAs("queries[]")] IEnumerable queries); [Patch("/databases/{databaseId}/collections/{collectionId}/documents/{documentId}")] - Task> UpdateDocument([Header("x-appwrite-session")] string session, string databaseId, string collectionId, string documentId, UpdateDocumentRequest request); + Task> UpdateDocument([Header("x-appwrite-session")] string? session, string databaseId, string collectionId, string documentId, UpdateDocumentRequest request); } From 3321755fd4f08d9e5936713dfdfece3f63723716 Mon Sep 17 00:00:00 2001 From: Matthew Parker Date: Sun, 8 Dec 2024 00:38:19 +0000 Subject: [PATCH 04/22] added tests for client List Documents --- .../DatabasesClientTests.ListDocuments.cs | 99 +++++++++++++++++++ .../Clients/Databases/DatabasesClientTests.cs | 38 +++++++ 2 files changed, 137 insertions(+) create mode 100644 tests/PinguApps.Appwrite.Client.Tests/Clients/Databases/DatabasesClientTests.ListDocuments.cs create mode 100644 tests/PinguApps.Appwrite.Client.Tests/Clients/Databases/DatabasesClientTests.cs diff --git a/tests/PinguApps.Appwrite.Client.Tests/Clients/Databases/DatabasesClientTests.ListDocuments.cs b/tests/PinguApps.Appwrite.Client.Tests/Clients/Databases/DatabasesClientTests.ListDocuments.cs new file mode 100644 index 00000000..9b7aab76 --- /dev/null +++ b/tests/PinguApps.Appwrite.Client.Tests/Clients/Databases/DatabasesClientTests.ListDocuments.cs @@ -0,0 +1,99 @@ +using System.Net; +using PinguApps.Appwrite.Shared.Requests.Databases; +using PinguApps.Appwrite.Shared.Tests; +using PinguApps.Appwrite.Shared.Utils; +using RichardSzalay.MockHttp; + +namespace PinguApps.Appwrite.Client.Tests.Clients.Databases; +public partial class DatabasesClientTests +{ + [Fact] + public async Task ListDocuments_ShouldReturnSuccess_WhenApiCallSucceeds() + { + // Arrange + var request = new ListDocumentsRequest + { + DatabaseId = IdUtils.GenerateUniqueId(), + CollectionId = IdUtils.GenerateUniqueId() + }; + + _mockHttp.Expect(HttpMethod.Get, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/documents") + .ExpectedHeaders() + .Respond(TestConstants.AppJson, TestConstants.DocumentsListResponse); + + // Act + var result = await _appwriteClient.Databases.ListDocuments(request); + + // Assert + Assert.True(result.Success); + } + + [Fact] + public async Task ListDocuments_ShouldProvideQueryParams_WhenQueriesProvided() + { + // Arrange + var query = Query.Limit(5); + var request = new ListDocumentsRequest + { + DatabaseId = IdUtils.GenerateUniqueId(), + CollectionId = IdUtils.GenerateUniqueId(), + Queries = [query] + }; + + _mockHttp.Expect(HttpMethod.Get, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/documents") + .ExpectedHeaders() + .WithQueryString($"queries[]={query.GetQueryString()}") + .Respond(TestConstants.AppJson, TestConstants.DocumentsListResponse); + + // Act + var result = await _appwriteClient.Databases.ListDocuments(request); + + // Assert + Assert.True(result.Success); + } + + [Fact] + public async Task ListDocuments_ShouldHandleException_WhenApiCallFails() + { + // Arrange + var request = new ListDocumentsRequest + { + DatabaseId = IdUtils.GenerateUniqueId(), + CollectionId = IdUtils.GenerateUniqueId() + }; + + _mockHttp.Expect(HttpMethod.Get, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/documents") + .ExpectedHeaders() + .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); + + // Act + var result = await _appwriteClient.Databases.ListDocuments(request); + + // Assert + Assert.True(result.IsError); + Assert.True(result.IsAppwriteError); + } + + [Fact] + public async Task ListDocuments_ShouldReturnErrorResponse_WhenExceptionOccurs() + { + // Arrange + var request = new ListDocumentsRequest + { + DatabaseId = IdUtils.GenerateUniqueId(), + CollectionId = IdUtils.GenerateUniqueId() + }; + + _mockHttp.Expect(HttpMethod.Get, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/documents") + .ExpectedHeaders() + .Throw(new HttpRequestException("An error occurred")); + + // Act + var result = await _appwriteClient.Databases.ListDocuments(request); + + // Assert + Assert.False(result.Success); + Assert.True(result.IsInternalError); + Assert.Equal("An error occurred", result.Result.AsT2.Message); + } +} diff --git a/tests/PinguApps.Appwrite.Client.Tests/Clients/Databases/DatabasesClientTests.cs b/tests/PinguApps.Appwrite.Client.Tests/Clients/Databases/DatabasesClientTests.cs new file mode 100644 index 00000000..c2b3d5d2 --- /dev/null +++ b/tests/PinguApps.Appwrite.Client.Tests/Clients/Databases/DatabasesClientTests.cs @@ -0,0 +1,38 @@ +using System.Text.Json; +using System.Text.Json.Serialization; +using Microsoft.Extensions.DependencyInjection; +using PinguApps.Appwrite.Shared.Converters; +using PinguApps.Appwrite.Shared.Tests; +using Refit; +using RichardSzalay.MockHttp; + +namespace PinguApps.Appwrite.Client.Tests.Clients.Databases; +public partial class DatabasesClientTests +{ + private readonly MockHttpMessageHandler _mockHttp; + private readonly IAppwriteClient _appwriteClient; + private readonly JsonSerializerOptions _jsonSerializerOptions; + + public DatabasesClientTests() + { + _mockHttp = new MockHttpMessageHandler(); + var services = new ServiceCollection(); + + services.AddAppwriteClientForServer(TestConstants.ProjectId, TestConstants.Endpoint, new RefitSettings + { + HttpMessageHandlerFactory = () => _mockHttp + }); + + var serviceProvider = services.BuildServiceProvider(); + + _appwriteClient = serviceProvider.GetRequiredService(); + + _jsonSerializerOptions = new JsonSerializerOptions + { + DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, + PropertyNamingPolicy = JsonNamingPolicy.CamelCase + }; + + _jsonSerializerOptions.Converters.Add(new IgnoreSdkExcludedPropertiesConverterFactory()); + } +} From dfebe3276684756fa353757c8045de7d7af4a173 Mon Sep 17 00:00:00 2001 From: Matthew Parker Date: Mon, 9 Dec 2024 00:05:35 +0000 Subject: [PATCH 05/22] Added WithData to CreateDocumentRequiestBuilder --- .../Databases/CreateDocumentRequestBuilder.cs | 56 ++++++- .../ICreateDocumentRequestBuilder.cs | 29 +++- .../CreateDocumentRequestBuilderTests.cs | 146 +++++++++++++++++- 3 files changed, 228 insertions(+), 3 deletions(-) diff --git a/src/PinguApps.Appwrite.Shared/Requests/Databases/CreateDocumentRequestBuilder.cs b/src/PinguApps.Appwrite.Shared/Requests/Databases/CreateDocumentRequestBuilder.cs index 108ce1ff..09a5e2ac 100644 --- a/src/PinguApps.Appwrite.Shared/Requests/Databases/CreateDocumentRequestBuilder.cs +++ b/src/PinguApps.Appwrite.Shared/Requests/Databases/CreateDocumentRequestBuilder.cs @@ -1,5 +1,12 @@ -using System.Collections.Generic; +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Reflection; +using System.Text.Json; +using System.Text.Json.Serialization; using PinguApps.Appwrite.Shared.Utils; +using static PinguApps.Appwrite.Shared.Requests.Databases.ICreateDocumentRequestBuilder; namespace PinguApps.Appwrite.Shared.Requests.Databases; internal class CreateDocumentRequestBuilder : ICreateDocumentRequestBuilder @@ -7,6 +14,14 @@ internal class CreateDocumentRequestBuilder : ICreateDocumentRequestBuilder private readonly CreateDocumentRequest _request = new(); private readonly Dictionary _data = []; + private static readonly JsonSerializerOptions _jsonOptions = new() + { + PropertyNamingPolicy = JsonNamingPolicy.CamelCase, + DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull + }; + + private static readonly ConcurrentDictionary _propertyCache = new(); + public ICreateDocumentRequestBuilder WithDatabaseId(string databaseId) { _request.DatabaseId = databaseId; @@ -43,6 +58,45 @@ public ICreateDocumentRequestBuilder AddField(string name, object? value) return this; } + public ICreateDocumentRequestBuilder WithData(T? data, Action? options = null) where T : class + { + if (data is null) + { + throw new ArgumentNullException(nameof(data)); + } + + var withDataOptions = new WithDataOptions(); + options?.Invoke(withDataOptions); + + var properties = _propertyCache.GetOrAdd(typeof(T), x => x.GetProperties(BindingFlags.Public | BindingFlags.Instance)); + + foreach (var property in properties) + { + if (!withDataOptions.ShouldIncludeProperty(property)) + { + continue; + } + + var jsonPropertyName = GetJsonPropertyName(property); + + var value = property.GetValue(data); + if (value is not null || !withDataOptions.IgnoreNullValues) + { + AddField(jsonPropertyName, value); + } + } + + return this; + } + + [ExcludeFromCodeCoverage] + private static string GetJsonPropertyName(PropertyInfo property) + { + return property.GetCustomAttribute()?.Name + ?? _jsonOptions.PropertyNamingPolicy?.ConvertName(property.Name) + ?? property.Name; + } + public CreateDocumentRequest Build() { _request.Data = _data; diff --git a/src/PinguApps.Appwrite.Shared/Requests/Databases/ICreateDocumentRequestBuilder.cs b/src/PinguApps.Appwrite.Shared/Requests/Databases/ICreateDocumentRequestBuilder.cs index 165071b6..bb3c171c 100644 --- a/src/PinguApps.Appwrite.Shared/Requests/Databases/ICreateDocumentRequestBuilder.cs +++ b/src/PinguApps.Appwrite.Shared/Requests/Databases/ICreateDocumentRequestBuilder.cs @@ -1,4 +1,7 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Text.Json.Serialization; using PinguApps.Appwrite.Shared.Utils; namespace PinguApps.Appwrite.Shared.Requests.Databases; @@ -42,4 +45,28 @@ public interface ICreateDocumentRequestBuilder /// Builds the document request /// CreateDocumentRequest Build(); + + /// + /// Adds your given data do the document data + /// + /// The type of your data object + /// The data + /// Options + ICreateDocumentRequestBuilder WithData(T? data, Action? options = null) where T : class; + + public class WithDataOptions + { + public bool IgnoreNullValues { get; set; } = true; + public Func? PropertyFilter { get; set; } + + public bool ShouldIncludeProperty(PropertyInfo property) + { + if (property.GetCustomAttribute() != null) + { + return false; + } + + return PropertyFilter?.Invoke(property) ?? true; + } + } } diff --git a/tests/PinguApps.Appwrite.Shared.Tests/Requests/Databases/CreateDocumentRequestBuilderTests.cs b/tests/PinguApps.Appwrite.Shared.Tests/Requests/Databases/CreateDocumentRequestBuilderTests.cs index 4c684fa5..3701a9c2 100644 --- a/tests/PinguApps.Appwrite.Shared.Tests/Requests/Databases/CreateDocumentRequestBuilderTests.cs +++ b/tests/PinguApps.Appwrite.Shared.Tests/Requests/Databases/CreateDocumentRequestBuilderTests.cs @@ -1,5 +1,7 @@ -using PinguApps.Appwrite.Shared.Requests.Databases; +using System.Text.Json.Serialization; +using PinguApps.Appwrite.Shared.Requests.Databases; using PinguApps.Appwrite.Shared.Utils; +using static PinguApps.Appwrite.Shared.Requests.Databases.ICreateDocumentRequestBuilder; namespace PinguApps.Appwrite.Shared.Tests.Requests.Databases; public class CreateDocumentRequestBuilderTests @@ -192,4 +194,146 @@ public void Build_WithNoFieldsAdded_CreatesEmptyDataDictionary() Assert.NotNull(request.Data); Assert.Empty(request.Data); } + + public class TestClass + { + public string? StringProp { get; set; } + public int IntProp { get; set; } + [JsonIgnore] + public string? IgnoredProp { get; set; } + [JsonPropertyName("custom")] + public string? CustomNameProp { get; set; } + } + + [Fact] + public void WithData_NullData_ThrowsArgumentNullException() + { + var builder = CreateDocumentRequest.CreateBuilder(); + + TestClass? nullData = null; + var ex = Assert.Throws(() => builder.WithData(nullData)); + Assert.Equal("data", ex.ParamName); + } + + [Fact] + public void WithData_NullOptions_UsesDefaultOptions() + { + var builder = CreateDocumentRequest.CreateBuilder(); + + var data = new TestClass { StringProp = "test" }; + builder.WithData(data, options: null); + // Assert AddField was called with "stringProp" and "test" + // You'll need to mock/verify this based on your implementation + } + + [Fact] + public void WithData_CustomOptions_AppliesOptions() + { + var builder = CreateDocumentRequest.CreateBuilder(); + + var data = new TestClass { StringProp = "test" }; + builder.WithData(data, options => options.IgnoreNullValues = false); + // Assert all properties were added, including nulls + } + + [Fact] + public void WithData_PropertyFilter_AppliesFilter() + { + var builder = CreateDocumentRequest.CreateBuilder(); + + var data = new TestClass { StringProp = "test", IntProp = 42 }; + builder.WithData(data, options => + options.PropertyFilter = prop => prop.PropertyType == typeof(string)); + // Assert only string properties were added + } + + [Fact] + public void WithData_JsonIgnoreAttribute_SkipsProperty() + { + var builder = CreateDocumentRequest.CreateBuilder(); + + var data = new TestClass { IgnoredProp = "ignored" }; + builder.WithData(data); + // Assert IgnoredProp was not added + } + + [Fact] + public void WithData_JsonPropertyNameAttribute_UsesCustomName() + { + var builder = CreateDocumentRequest.CreateBuilder(); + + var data = new TestClass { CustomNameProp = "test" }; + builder.WithData(data); + // Assert AddField was called with "custom" instead of "customNameProp" + } + + [Fact] + public void WithData_NullValue_IgnoredByDefault() + { + var builder = CreateDocumentRequest.CreateBuilder(); + + var data = new TestClass { StringProp = null }; + builder.WithData(data); + // Assert AddField was not called for StringProp + } + + [Fact] + public void WithData_NullValue_IncludedWhenIgnoreNullValuesFalse() + { + var builder = CreateDocumentRequest.CreateBuilder(); + + var data = new TestClass { StringProp = null }; + builder.WithData(data, options => options.IgnoreNullValues = false); + // Assert AddField was called with null value + } + + [Fact] + public void WithData_PropertyCacheReuse_CachesProperties() + { + var builder = CreateDocumentRequest.CreateBuilder(); + + var data1 = new TestClass(); + var data2 = new TestClass(); + builder.WithData(data1); + builder.WithData(data2); + // Assert properties were cached (you'll need to expose cache or use reflection to verify) + } + + [Fact] + public void ShouldIncludeProperty_NoAttributeNoFilter_ReturnsTrue() + { + var options = new WithDataOptions(); + var prop = typeof(TestClass).GetProperty(nameof(TestClass.StringProp))!; + Assert.True(options.ShouldIncludeProperty(prop)); + } + + [Fact] + public void ShouldIncludeProperty_JsonIgnoreAttribute_ReturnsFalse() + { + var options = new WithDataOptions(); + var prop = typeof(TestClass).GetProperty(nameof(TestClass.IgnoredProp))!; + Assert.False(options.ShouldIncludeProperty(prop)); + } + + [Fact] + public void ShouldIncludeProperty_CustomFilterTrue_ReturnsTrue() + { + var options = new WithDataOptions + { + PropertyFilter = _ => true + }; + var prop = typeof(TestClass).GetProperty(nameof(TestClass.StringProp))!; + Assert.True(options.ShouldIncludeProperty(prop)); + } + + [Fact] + public void ShouldIncludeProperty_CustomFilterFalse_ReturnsFalse() + { + var options = new WithDataOptions + { + PropertyFilter = _ => false + }; + var prop = typeof(TestClass).GetProperty(nameof(TestClass.StringProp))!; + Assert.False(options.ShouldIncludeProperty(prop)); + } } From 6a73ee8e6224551fffd62de44986757c99776d41 Mon Sep 17 00:00:00 2001 From: Matthew Parker Date: Mon, 9 Dec 2024 00:05:58 +0000 Subject: [PATCH 06/22] Implemented CreateDocument (untested) --- .../Clients/DatabasesClient.cs | 17 +++++++++++++++-- .../Clients/IDatabasesClient.cs | 7 ++++++- .../Clients/DatabasesClient.cs | 17 +++++++++++++++-- .../Clients/IDatabasesClient.cs | 7 ++++++- 4 files changed, 42 insertions(+), 6 deletions(-) diff --git a/src/PinguApps.Appwrite.Client/Clients/DatabasesClient.cs b/src/PinguApps.Appwrite.Client/Clients/DatabasesClient.cs index d1f3833b..6dbdfcac 100644 --- a/src/PinguApps.Appwrite.Client/Clients/DatabasesClient.cs +++ b/src/PinguApps.Appwrite.Client/Clients/DatabasesClient.cs @@ -36,9 +36,22 @@ public async Task> ListDocuments(ListDocumentsRequ } } - [ExcludeFromCodeCoverage] /// - public Task> CreateDocument(CreateDocumentRequest request) => throw new NotImplementedException(); + public async Task> CreateDocument(CreateDocumentRequest request) + { + try + { + request.Validate(true); + + var result = await _databasesApi.CreateDocument(GetCurrentSession(), request.DatabaseId, request.CollectionId, request); + + return result.GetApiResponse(); + } + catch (Exception e) + { + return e.GetExceptionResponse(); + } + } [ExcludeFromCodeCoverage] /// diff --git a/src/PinguApps.Appwrite.Client/Clients/IDatabasesClient.cs b/src/PinguApps.Appwrite.Client/Clients/IDatabasesClient.cs index e2e4baee..8bd83d51 100644 --- a/src/PinguApps.Appwrite.Client/Clients/IDatabasesClient.cs +++ b/src/PinguApps.Appwrite.Client/Clients/IDatabasesClient.cs @@ -23,7 +23,12 @@ public interface IDatabasesClient /// The documents list Task> ListDocuments(ListDocumentsRequest request); - [Obsolete("Endpoint not yet implemented.")] + /// + /// Create a new Document. Before using this route, you should create a new collection resource using either a server integration API or directly from your database console. + /// Appwrite Docs + /// + /// The request content + /// The document Task> CreateDocument(CreateDocumentRequest request); [Obsolete("Endpoint not yet implemented.")] diff --git a/src/PinguApps.Appwrite.Server/Clients/DatabasesClient.cs b/src/PinguApps.Appwrite.Server/Clients/DatabasesClient.cs index b0d92d1d..72953a1c 100644 --- a/src/PinguApps.Appwrite.Server/Clients/DatabasesClient.cs +++ b/src/PinguApps.Appwrite.Server/Clients/DatabasesClient.cs @@ -599,9 +599,22 @@ public async Task> ListDocuments(ListDocumentsRequ } } - [ExcludeFromCodeCoverage] /// - public Task> CreateDocument(CreateDocumentRequest request) => throw new NotImplementedException(); + public async Task> CreateDocument(CreateDocumentRequest request) + { + try + { + request.Validate(true); + + var result = await _databasesApi.CreateDocument(request.DatabaseId, request.CollectionId, request); + + return result.GetApiResponse(); + } + catch (Exception e) + { + return e.GetExceptionResponse(); + } + } [ExcludeFromCodeCoverage] /// diff --git a/src/PinguApps.Appwrite.Server/Clients/IDatabasesClient.cs b/src/PinguApps.Appwrite.Server/Clients/IDatabasesClient.cs index fc689c8a..e5d43285 100644 --- a/src/PinguApps.Appwrite.Server/Clients/IDatabasesClient.cs +++ b/src/PinguApps.Appwrite.Server/Clients/IDatabasesClient.cs @@ -290,7 +290,12 @@ public interface IDatabasesClient /// The documents list Task> ListDocuments(ListDocumentsRequest request); - [Obsolete("Endpoint not yet implemented.")] + /// + /// Create a new Document. Before using this route, you should create a new collection resource using either or directly from your database console. + /// Appwrite Docs + /// + /// The request content + /// The document Task> CreateDocument(CreateDocumentRequest request); [Obsolete("Endpoint not yet implemented.")] From 663ca32f1169455799f5274433c8e93721072c6a Mon Sep 17 00:00:00 2001 From: Matthew Parker Date: Tue, 10 Dec 2024 16:39:11 +0000 Subject: [PATCH 07/22] Update App.cs --- src/PinguApps.Appwrite.Playground/App.cs | 34 +++++++++++------------- 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/src/PinguApps.Appwrite.Playground/App.cs b/src/PinguApps.Appwrite.Playground/App.cs index 0bcff66c..ccc0cb9f 100644 --- a/src/PinguApps.Appwrite.Playground/App.cs +++ b/src/PinguApps.Appwrite.Playground/App.cs @@ -1,5 +1,4 @@ using Microsoft.Extensions.Configuration; -using PinguApps.Appwrite.Shared.Requests.Databases; namespace PinguApps.Appwrite.Playground; internal class App @@ -17,28 +16,27 @@ public App(Client.IAppwriteClient client, Server.Clients.IAppwriteClient server, public async Task Run(string[] args) { - var request = new ListDocumentsRequest() - { - DatabaseId = "67541a2800221703e717", - CollectionId = "67541a37001514b81821" - }; + //var request = CreateDocumentRequest.CreateBuilder() + // .WithDatabaseId("") + // .WithCollectionId("") + // .AddField - var serverResponse = await _server.Databases.ListDocuments(request); + //var serverResponse = await _server.Databases.ListDocuments(request); - Console.WriteLine(serverResponse.Result.Match( - result => result.ToString(), - appwriteError => appwriteError.Message, - internalError => internalError.Message)); + //Console.WriteLine(serverResponse.Result.Match( + // result => result.ToString(), + // appwriteError => appwriteError.Message, + // internalError => internalError.Message)); - Console.WriteLine("###############################################################################"); + //Console.WriteLine("###############################################################################"); - _client.SetSession(_session); + //_client.SetSession(_session); - var clientResponse = await _client.Databases.ListDocuments(request); + //var clientResponse = await _client.Databases.ListDocuments(request); - Console.WriteLine(clientResponse.Result.Match( - result => result.ToString(), - appwriteError => appwriteError.Message, - internalError => internalError.Message)); + //Console.WriteLine(clientResponse.Result.Match( + // result => result.ToString(), + // appwriteError => appwriteError.Message, + // internalError => internalError.Message)); } } From 2c07a4f9f3c983ad7e8f25cf5ba1ce7afea1b30c Mon Sep 17 00:00:00 2001 From: Matthew Parker Date: Tue, 10 Dec 2024 17:54:01 +0000 Subject: [PATCH 08/22] Completed manual testing of CreateDocument --- src/PinguApps.Appwrite.Playground/App.cs | 39 +++++++++++-------- .../ICreateDocumentRequestBuilder.cs | 12 +++++- 2 files changed, 34 insertions(+), 17 deletions(-) diff --git a/src/PinguApps.Appwrite.Playground/App.cs b/src/PinguApps.Appwrite.Playground/App.cs index ccc0cb9f..9cd1b4ad 100644 --- a/src/PinguApps.Appwrite.Playground/App.cs +++ b/src/PinguApps.Appwrite.Playground/App.cs @@ -1,4 +1,6 @@ using Microsoft.Extensions.Configuration; +using PinguApps.Appwrite.Shared.Requests.Databases; +using PinguApps.Appwrite.Shared.Utils; namespace PinguApps.Appwrite.Playground; internal class App @@ -16,27 +18,32 @@ public App(Client.IAppwriteClient client, Server.Clients.IAppwriteClient server, public async Task Run(string[] args) { - //var request = CreateDocumentRequest.CreateBuilder() - // .WithDatabaseId("") - // .WithCollectionId("") - // .AddField + var request = CreateDocumentRequest.CreateBuilder() + .WithDatabaseId("67541a2800221703e717") + .WithCollectionId("67541a37001514b81821") + .WithData(new + { + test = "TEST", + boolAttribute = false + }) + .Build(); - //var serverResponse = await _server.Databases.ListDocuments(request); + var serverResponse = await _server.Databases.CreateDocument(request); - //Console.WriteLine(serverResponse.Result.Match( - // result => result.ToString(), - // appwriteError => appwriteError.Message, - // internalError => internalError.Message)); + Console.WriteLine(serverResponse.Result.Match( + result => result.ToString(), + appwriteError => appwriteError.Message, + internalError => internalError.Message)); - //Console.WriteLine("###############################################################################"); + Console.WriteLine("###############################################################################"); - //_client.SetSession(_session); + request.DocumentId = IdUtils.GenerateUniqueId(); - //var clientResponse = await _client.Databases.ListDocuments(request); + var clientResponse = await _client.Databases.CreateDocument(request); - //Console.WriteLine(clientResponse.Result.Match( - // result => result.ToString(), - // appwriteError => appwriteError.Message, - // internalError => internalError.Message)); + Console.WriteLine(clientResponse.Result.Match( + result => result.ToString(), + appwriteError => appwriteError.Message, + internalError => internalError.Message)); } } diff --git a/src/PinguApps.Appwrite.Shared/Requests/Databases/ICreateDocumentRequestBuilder.cs b/src/PinguApps.Appwrite.Shared/Requests/Databases/ICreateDocumentRequestBuilder.cs index bb3c171c..e0a73873 100644 --- a/src/PinguApps.Appwrite.Shared/Requests/Databases/ICreateDocumentRequestBuilder.cs +++ b/src/PinguApps.Appwrite.Shared/Requests/Databases/ICreateDocumentRequestBuilder.cs @@ -54,12 +54,22 @@ public interface ICreateDocumentRequestBuilder /// Options ICreateDocumentRequestBuilder WithData(T? data, Action? options = null) where T : class; + /// + /// Options for adding data to the document + /// public class WithDataOptions { + /// + /// Whether to ignore null values + /// public bool IgnoreNullValues { get; set; } = true; + + /// + /// A filter for properties + /// public Func? PropertyFilter { get; set; } - public bool ShouldIncludeProperty(PropertyInfo property) + internal bool ShouldIncludeProperty(PropertyInfo property) { if (property.GetCustomAttribute() != null) { From 33ab94ab28355d95f0064c314ae539f47c3f7018 Mon Sep 17 00:00:00 2001 From: Matthew Parker Date: Tue, 10 Dec 2024 17:55:56 +0000 Subject: [PATCH 09/22] Added extra xml docs to instruct user on how to create a create document request --- .../Requests/Databases/CreateDocumentRequest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PinguApps.Appwrite.Shared/Requests/Databases/CreateDocumentRequest.cs b/src/PinguApps.Appwrite.Shared/Requests/Databases/CreateDocumentRequest.cs index afc131f1..2038f46d 100644 --- a/src/PinguApps.Appwrite.Shared/Requests/Databases/CreateDocumentRequest.cs +++ b/src/PinguApps.Appwrite.Shared/Requests/Databases/CreateDocumentRequest.cs @@ -3,7 +3,7 @@ namespace PinguApps.Appwrite.Shared.Requests.Databases; /// -/// The request to create a document +/// The request to create a document. To instantiate, use /// public class CreateDocumentRequest : CreateDocumentRequest> { From 596a77e6f7a15d27c18f0b91546bf80d7e4bb6a4 Mon Sep 17 00:00:00 2001 From: Matthew Parker Date: Tue, 10 Dec 2024 18:09:37 +0000 Subject: [PATCH 10/22] Added tests for create document --- .../DatabasesClientTests.CreateDocument.cs | 78 +++++++++++++++++++ .../DatabasesClientTests.CreateDocument.cs | 78 +++++++++++++++++++ 2 files changed, 156 insertions(+) create mode 100644 tests/PinguApps.Appwrite.Client.Tests/Clients/Databases/DatabasesClientTests.CreateDocument.cs create mode 100644 tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.CreateDocument.cs diff --git a/tests/PinguApps.Appwrite.Client.Tests/Clients/Databases/DatabasesClientTests.CreateDocument.cs b/tests/PinguApps.Appwrite.Client.Tests/Clients/Databases/DatabasesClientTests.CreateDocument.cs new file mode 100644 index 00000000..7fda4022 --- /dev/null +++ b/tests/PinguApps.Appwrite.Client.Tests/Clients/Databases/DatabasesClientTests.CreateDocument.cs @@ -0,0 +1,78 @@ +using System.Net; +using PinguApps.Appwrite.Shared.Requests.Databases; +using PinguApps.Appwrite.Shared.Tests; +using PinguApps.Appwrite.Shared.Utils; +using RichardSzalay.MockHttp; + +namespace PinguApps.Appwrite.Client.Tests.Clients.Databases; +public partial class DatabasesClientTests +{ + [Fact] + public async Task CreateDocument_ShouldReturnSuccess_WhenApiCallSucceeds() + { + // Arrange + var request = CreateDocumentRequest.CreateBuilder() + .WithDatabaseId(IdUtils.GenerateUniqueId()) + .WithCollectionId(IdUtils.GenerateUniqueId()) + .AddField("AttributeName", "MyValue") + .Build(); + + _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/documents") + .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) + .Respond(TestConstants.AppJson, TestConstants.DocumentResponse); + + // Act + var result = await _appwriteClient.Databases.CreateDocument(request); + + // Assert + Assert.True(result.Success); + } + + [Fact] + public async Task CreateDocument_ShouldHandleException_WhenApiCallFails() + { + // Arrange + var request = CreateDocumentRequest.CreateBuilder() + .WithDatabaseId(IdUtils.GenerateUniqueId()) + .WithCollectionId(IdUtils.GenerateUniqueId()) + .AddField("AttributeName", "MyValue") + .Build(); + + _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/documents") + .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) + .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); + + // Act + var result = await _appwriteClient.Databases.CreateDocument(request); + + // Assert + Assert.True(result.IsError); + Assert.True(result.IsAppwriteError); + } + + [Fact] + public async Task CreateDocument_ShouldReturnErrorResponse_WhenExceptionOccurs() + { + // Arrange + var request = CreateDocumentRequest.CreateBuilder() + .WithDatabaseId(IdUtils.GenerateUniqueId()) + .WithCollectionId(IdUtils.GenerateUniqueId()) + .AddField("AttributeName", "MyValue") + .Build(); + + _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/documents") + .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) + .Throw(new HttpRequestException("An error occurred")); + + // Act + var result = await _appwriteClient.Databases.CreateDocument(request); + + // Assert + Assert.False(result.Success); + Assert.True(result.IsInternalError); + Assert.Equal("An error occurred", result.Result.AsT2.Message); + } +} diff --git a/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.CreateDocument.cs b/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.CreateDocument.cs new file mode 100644 index 00000000..35cfa091 --- /dev/null +++ b/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.CreateDocument.cs @@ -0,0 +1,78 @@ +using System.Net; +using PinguApps.Appwrite.Shared.Requests.Databases; +using PinguApps.Appwrite.Shared.Tests; +using PinguApps.Appwrite.Shared.Utils; +using RichardSzalay.MockHttp; + +namespace PinguApps.Appwrite.Server.Tests.Clients.Databases; +public partial class DatabasesClientTests +{ + [Fact] + public async Task CreateDocument_ShouldReturnSuccess_WhenApiCallSucceeds() + { + // Arrange + var request = CreateDocumentRequest.CreateBuilder() + .WithDatabaseId(IdUtils.GenerateUniqueId()) + .WithCollectionId(IdUtils.GenerateUniqueId()) + .AddField("AttributeName", "MyValue") + .Build(); + + _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/documents") + .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) + .Respond(TestConstants.AppJson, TestConstants.DocumentResponse); + + // Act + var result = await _appwriteClient.Databases.CreateDocument(request); + + // Assert + Assert.True(result.Success); + } + + [Fact] + public async Task CreateDocument_ShouldHandleException_WhenApiCallFails() + { + // Arrange + var request = CreateDocumentRequest.CreateBuilder() + .WithDatabaseId(IdUtils.GenerateUniqueId()) + .WithCollectionId(IdUtils.GenerateUniqueId()) + .AddField("AttributeName", "MyValue") + .Build(); + + _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/documents") + .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) + .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); + + // Act + var result = await _appwriteClient.Databases.CreateDocument(request); + + // Assert + Assert.True(result.IsError); + Assert.True(result.IsAppwriteError); + } + + [Fact] + public async Task CreateDocument_ShouldReturnErrorResponse_WhenExceptionOccurs() + { + // Arrange + var request = CreateDocumentRequest.CreateBuilder() + .WithDatabaseId(IdUtils.GenerateUniqueId()) + .WithCollectionId(IdUtils.GenerateUniqueId()) + .AddField("AttributeName", "MyValue") + .Build(); + + _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/documents") + .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) + .Throw(new HttpRequestException("An error occurred")); + + // Act + var result = await _appwriteClient.Databases.CreateDocument(request); + + // Assert + Assert.False(result.Success); + Assert.True(result.IsInternalError); + Assert.Equal("An error occurred", result.Result.AsT2.Message); + } +} From f301803073115e64cbc183525c688a8944c41b86 Mon Sep 17 00:00:00 2001 From: Matthew Parker Date: Tue, 10 Dec 2024 18:19:25 +0000 Subject: [PATCH 11/22] Updated tests that were missing WithJsonContent --- .../Databases/DatabasesClientTests.CreateBooleanAttribute.cs | 3 +++ .../Clients/Databases/DatabasesClientTests.CreateCollection.cs | 3 +++ .../Clients/Databases/DatabasesClientTests.CreateDatabase.cs | 3 +++ .../Databases/DatabasesClientTests.CreateDatetimeAttribute.cs | 3 +++ .../Databases/DatabasesClientTests.CreateEmailAttribute.cs | 3 +++ .../Databases/DatabasesClientTests.CreateEnumAttribute.cs | 3 +++ .../Databases/DatabasesClientTests.CreateFloatAttribute.cs | 3 +++ .../Clients/Databases/DatabasesClientTests.CreateIndex.cs | 3 +++ .../Databases/DatabasesClientTests.CreateIntegerAttribute.cs | 3 +++ .../Databases/DatabasesClientTests.CreateIpAttribute.cs | 3 +++ .../DatabasesClientTests.CreateRelationshipAttribute.cs | 3 +++ .../Databases/DatabasesClientTests.CreateStringAttribute.cs | 3 +++ .../Databases/DatabasesClientTests.CreateUrlAttribute.cs | 3 +++ .../Databases/DatabasesClientTests.UpdateBooleanAttribute.cs | 3 +++ .../Clients/Databases/DatabasesClientTests.UpdateCollection.cs | 3 +++ .../Clients/Databases/DatabasesClientTests.UpdateDatabase.cs | 3 +++ .../Databases/DatabasesClientTests.UpdateDatetimeAttribute.cs | 3 +++ .../Databases/DatabasesClientTests.UpdateEmailAttribute.cs | 3 +++ .../Databases/DatabasesClientTests.UpdateEnumAttribute.cs | 3 +++ .../Databases/DatabasesClientTests.UpdateFloatAttribute.cs | 3 +++ .../Databases/DatabasesClientTests.UpdateIntegerAttribute.cs | 3 +++ .../Databases/DatabasesClientTests.UpdateIpAttribute.cs | 3 +++ .../DatabasesClientTests.UpdateRelationshipAttribute.cs | 3 +++ .../Databases/DatabasesClientTests.UpdateStringAttribute.cs | 3 +++ .../Databases/DatabasesClientTests.UpdateUrlAttribute.cs | 3 +++ 25 files changed, 75 insertions(+) diff --git a/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.CreateBooleanAttribute.cs b/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.CreateBooleanAttribute.cs index db32ba61..01638421 100644 --- a/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.CreateBooleanAttribute.cs +++ b/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.CreateBooleanAttribute.cs @@ -20,6 +20,7 @@ public async Task CreateBooleanAttribute_ShouldReturnSuccess_WhenApiCallSucceeds _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/attributes/boolean") .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) .Respond(TestConstants.AppJson, TestConstants.AttributeBooleanResponse); // Act @@ -42,6 +43,7 @@ public async Task CreateBooleanAttribute_ShouldHandleException_WhenApiCallFails( _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/attributes/boolean") .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); // Act @@ -65,6 +67,7 @@ public async Task CreateBooleanAttribute_ShouldReturnErrorResponse_WhenException _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/attributes/boolean") .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) .Throw(new HttpRequestException("An error occurred")); // Act diff --git a/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.CreateCollection.cs b/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.CreateCollection.cs index 90789f44..5fcbcf3b 100644 --- a/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.CreateCollection.cs +++ b/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.CreateCollection.cs @@ -19,6 +19,7 @@ public async Task CreateCollection_ShouldReturnSuccess_WhenApiCallSucceeds() _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections") .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) .Respond(TestConstants.AppJson, TestConstants.CollectionResponse); // Act @@ -40,6 +41,7 @@ public async Task CreateCollection_ShouldHandleException_WhenApiCallFails() _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections") .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); // Act @@ -62,6 +64,7 @@ public async Task CreateCollection_ShouldReturnErrorResponse_WhenExceptionOccurs _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections") .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) .Throw(new HttpRequestException("An error occurred")); // Act diff --git a/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.CreateDatabase.cs b/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.CreateDatabase.cs index 8fc8adbb..0b53cba2 100644 --- a/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.CreateDatabase.cs +++ b/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.CreateDatabase.cs @@ -17,6 +17,7 @@ public async Task CreateDatabase_ShouldReturnSuccess_WhenApiCallSucceeds() _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/databases") .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) .Respond(TestConstants.AppJson, TestConstants.DatabaseResponse); // Act @@ -37,6 +38,7 @@ public async Task CreateDatabase_ShouldHandleException_WhenApiCallFails() _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/databases") .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); // Act @@ -58,6 +60,7 @@ public async Task CreateDatabase_ShouldReturnErrorResponse_WhenExceptionOccurs() _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/databases") .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) .Throw(new HttpRequestException("An error occurred")); // Act diff --git a/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.CreateDatetimeAttribute.cs b/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.CreateDatetimeAttribute.cs index c015c652..95c3f667 100644 --- a/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.CreateDatetimeAttribute.cs +++ b/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.CreateDatetimeAttribute.cs @@ -20,6 +20,7 @@ public async Task CreateDatetimeAttribute_ShouldReturnSuccess_WhenApiCallSucceed _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/attributes/datetime") .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) .Respond(TestConstants.AppJson, TestConstants.AttributeDatetimeResponse); // Act @@ -42,6 +43,7 @@ public async Task CreateDatetimeAttribute_ShouldHandleException_WhenApiCallFails _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/attributes/datetime") .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); // Act @@ -65,6 +67,7 @@ public async Task CreateDatetimeAttribute_ShouldReturnErrorResponse_WhenExceptio _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/attributes/datetime") .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) .Throw(new HttpRequestException("An error occurred")); // Act diff --git a/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.CreateEmailAttribute.cs b/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.CreateEmailAttribute.cs index 882dd613..b7a8ec75 100644 --- a/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.CreateEmailAttribute.cs +++ b/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.CreateEmailAttribute.cs @@ -20,6 +20,7 @@ public async Task CreateEmailAttribute_ShouldReturnSuccess_WhenApiCallSucceeds() _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/attributes/email") .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) .Respond(TestConstants.AppJson, TestConstants.AttributeEmailResponse); // Act @@ -42,6 +43,7 @@ public async Task CreateEmailAttribute_ShouldHandleException_WhenApiCallFails() _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/attributes/email") .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); // Act @@ -65,6 +67,7 @@ public async Task CreateEmailAttribute_ShouldReturnErrorResponse_WhenExceptionOc _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/attributes/email") .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) .Throw(new HttpRequestException("An error occurred")); // Act diff --git a/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.CreateEnumAttribute.cs b/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.CreateEnumAttribute.cs index 49554880..d0e59d3e 100644 --- a/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.CreateEnumAttribute.cs +++ b/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.CreateEnumAttribute.cs @@ -21,6 +21,7 @@ public async Task CreateEnumAttribute_ShouldReturnSuccess_WhenApiCallSucceeds() _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/attributes/enum") .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) .Respond(TestConstants.AppJson, TestConstants.AttributeEnumResponse); // Act @@ -44,6 +45,7 @@ public async Task CreateEnumAttribute_ShouldHandleException_WhenApiCallFails() _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/attributes/enum") .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); // Act @@ -68,6 +70,7 @@ public async Task CreateEnumAttribute_ShouldReturnErrorResponse_WhenExceptionOcc _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/attributes/enum") .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) .Throw(new HttpRequestException("An error occurred")); // Act diff --git a/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.CreateFloatAttribute.cs b/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.CreateFloatAttribute.cs index dc30c08c..e1a7a4d2 100644 --- a/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.CreateFloatAttribute.cs +++ b/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.CreateFloatAttribute.cs @@ -20,6 +20,7 @@ public async Task CreateFloatAttribute_ShouldReturnSuccess_WhenApiCallSucceeds() _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/attributes/float") .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) .Respond(TestConstants.AppJson, TestConstants.AttributeFloatResponse); // Act @@ -42,6 +43,7 @@ public async Task CreateFloatAttribute_ShouldHandleException_WhenApiCallFails() _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/attributes/float") .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); // Act @@ -65,6 +67,7 @@ public async Task CreateFloatAttribute_ShouldReturnErrorResponse_WhenExceptionOc _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/attributes/float") .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) .Throw(new HttpRequestException("An error occurred")); // Act diff --git a/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.CreateIndex.cs b/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.CreateIndex.cs index b6cf11e6..91a582fd 100644 --- a/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.CreateIndex.cs +++ b/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.CreateIndex.cs @@ -24,6 +24,7 @@ public async Task CreateIndex_ShouldReturnSuccess_WhenApiCallSucceeds() _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/indexes") .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) .Respond(TestConstants.AppJson, TestConstants.IndexResponse); // Act @@ -49,6 +50,7 @@ public async Task CreateIndex_ShouldHandleException_WhenApiCallFails() _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/indexes") .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); // Act @@ -75,6 +77,7 @@ public async Task CreateIndex_ShouldReturnErrorResponse_WhenExceptionOccurs() _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/indexes") .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) .Throw(new HttpRequestException("An error occurred")); // Act diff --git a/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.CreateIntegerAttribute.cs b/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.CreateIntegerAttribute.cs index 634f723f..8aa904a6 100644 --- a/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.CreateIntegerAttribute.cs +++ b/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.CreateIntegerAttribute.cs @@ -20,6 +20,7 @@ public async Task CreateIntegerAttribute_ShouldReturnSuccess_WhenApiCallSucceeds _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/attributes/integer") .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) .Respond(TestConstants.AppJson, TestConstants.AttributeIntegerResponse); // Act @@ -42,6 +43,7 @@ public async Task CreateIntegerAttribute_ShouldHandleException_WhenApiCallFails( _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/attributes/integer") .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); // Act @@ -65,6 +67,7 @@ public async Task CreateIntegerAttribute_ShouldReturnErrorResponse_WhenException _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/attributes/integer") .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) .Throw(new HttpRequestException("An error occurred")); // Act diff --git a/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.CreateIpAttribute.cs b/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.CreateIpAttribute.cs index c0bd4966..d2b21fb9 100644 --- a/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.CreateIpAttribute.cs +++ b/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.CreateIpAttribute.cs @@ -20,6 +20,7 @@ public async Task CreateIpAttribute_ShouldReturnSuccess_WhenApiCallSucceeds() _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/attributes/ip") .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) .Respond(TestConstants.AppJson, TestConstants.AttributeIpResponse); // Act @@ -42,6 +43,7 @@ public async Task CreateIpAttribute_ShouldHandleException_WhenApiCallFails() _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/attributes/ip") .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); // Act @@ -65,6 +67,7 @@ public async Task CreateIpAttribute_ShouldReturnErrorResponse_WhenExceptionOccur _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/attributes/ip") .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) .Throw(new HttpRequestException("An error occurred")); // Act diff --git a/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.CreateRelationshipAttribute.cs b/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.CreateRelationshipAttribute.cs index 6f95a3a0..9779c068 100644 --- a/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.CreateRelationshipAttribute.cs +++ b/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.CreateRelationshipAttribute.cs @@ -21,6 +21,7 @@ public async Task CreateRelationshipAttribute_ShouldReturnSuccess_WhenApiCallSuc _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/attributes/relationship") .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) .Respond(TestConstants.AppJson, TestConstants.AttributeRelationshipResponse); // Act @@ -44,6 +45,7 @@ public async Task CreateRelationshipAttribute_ShouldHandleException_WhenApiCallF _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/attributes/relationship") .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); // Act @@ -68,6 +70,7 @@ public async Task CreateRelationshipAttribute_ShouldReturnErrorResponse_WhenExce _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/attributes/relationship") .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) .Throw(new HttpRequestException("An error occurred")); // Act diff --git a/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.CreateStringAttribute.cs b/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.CreateStringAttribute.cs index fe5713b2..b456a3cf 100644 --- a/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.CreateStringAttribute.cs +++ b/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.CreateStringAttribute.cs @@ -21,6 +21,7 @@ public async Task CreateStringAttribute_ShouldReturnSuccess_WhenApiCallSucceeds( _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/attributes/string") .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) .Respond(TestConstants.AppJson, TestConstants.AttributeStringResponse); // Act @@ -44,6 +45,7 @@ public async Task CreateStringAttribute_ShouldHandleException_WhenApiCallFails() _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/attributes/string") .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); // Act @@ -68,6 +70,7 @@ public async Task CreateStringAttribute_ShouldReturnErrorResponse_WhenExceptionO _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/attributes/string") .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) .Throw(new HttpRequestException("An error occurred")); // Act diff --git a/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.CreateUrlAttribute.cs b/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.CreateUrlAttribute.cs index 1dab125b..14d2aa97 100644 --- a/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.CreateUrlAttribute.cs +++ b/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.CreateUrlAttribute.cs @@ -20,6 +20,7 @@ public async Task CreateUrlAttribute_ShouldReturnSuccess_WhenApiCallSucceeds() _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/attributes/url") .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) .Respond(TestConstants.AppJson, TestConstants.AttributeUrlResponse); // Act @@ -42,6 +43,7 @@ public async Task CreateUrlAttribute_ShouldHandleException_WhenApiCallFails() _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/attributes/url") .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); // Act @@ -65,6 +67,7 @@ public async Task CreateUrlAttribute_ShouldReturnErrorResponse_WhenExceptionOccu _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/attributes/url") .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) .Throw(new HttpRequestException("An error occurred")); // Act diff --git a/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.UpdateBooleanAttribute.cs b/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.UpdateBooleanAttribute.cs index ce3d356d..b0ba2cba 100644 --- a/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.UpdateBooleanAttribute.cs +++ b/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.UpdateBooleanAttribute.cs @@ -20,6 +20,7 @@ public async Task UpdateBooleanAttribute_ShouldReturnSuccess_WhenApiCallSucceeds _mockHttp.Expect(HttpMethod.Patch, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/attributes/boolean/{request.Key}") .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) .Respond(TestConstants.AppJson, TestConstants.AttributeBooleanResponse); // Act @@ -42,6 +43,7 @@ public async Task UpdateBooleanAttribute_ShouldHandleException_WhenApiCallFails( _mockHttp.Expect(HttpMethod.Patch, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/attributes/boolean/{request.Key}") .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); // Act @@ -65,6 +67,7 @@ public async Task UpdateBooleanAttribute_ShouldReturnErrorResponse_WhenException _mockHttp.Expect(HttpMethod.Patch, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/attributes/boolean/{request.Key}") .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) .Throw(new HttpRequestException("An error occurred")); // Act diff --git a/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.UpdateCollection.cs b/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.UpdateCollection.cs index 93643e21..c5061c86 100644 --- a/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.UpdateCollection.cs +++ b/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.UpdateCollection.cs @@ -20,6 +20,7 @@ public async Task UpdateCollection_ShouldReturnSuccess_WhenApiCallSucceeds() _mockHttp.Expect(HttpMethod.Put, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}") .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) .Respond(TestConstants.AppJson, TestConstants.CollectionResponse); // Act @@ -42,6 +43,7 @@ public async Task UpdateCollection_ShouldHandleException_WhenApiCallFails() _mockHttp.Expect(HttpMethod.Put, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}") .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); // Act @@ -65,6 +67,7 @@ public async Task UpdateCollection_ShouldReturnErrorResponse_WhenExceptionOccurs _mockHttp.Expect(HttpMethod.Put, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}") .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) .Throw(new HttpRequestException("An error occurred")); // Act diff --git a/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.UpdateDatabase.cs b/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.UpdateDatabase.cs index c1ea6931..79a5b6d8 100644 --- a/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.UpdateDatabase.cs +++ b/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.UpdateDatabase.cs @@ -19,6 +19,7 @@ public async Task UpdateDatabase_ShouldReturnSuccess_WhenApiCallSucceeds() _mockHttp.Expect(HttpMethod.Put, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}") .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) .Respond(TestConstants.AppJson, TestConstants.DatabaseResponse); // Act @@ -40,6 +41,7 @@ public async Task UpdateDatabase_ShouldHandleException_WhenApiCallFails() _mockHttp.Expect(HttpMethod.Put, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}") .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); // Act @@ -62,6 +64,7 @@ public async Task UpdateDatabase_ShouldReturnErrorResponse_WhenExceptionOccurs() _mockHttp.Expect(HttpMethod.Put, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}") .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) .Throw(new HttpRequestException("An error occurred")); // Act diff --git a/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.UpdateDatetimeAttribute.cs b/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.UpdateDatetimeAttribute.cs index 179d7b73..b8f4c021 100644 --- a/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.UpdateDatetimeAttribute.cs +++ b/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.UpdateDatetimeAttribute.cs @@ -21,6 +21,7 @@ public async Task UpdateDatetimeAttribute_ShouldReturnSuccess_WhenApiCallSucceed _mockHttp.Expect(HttpMethod.Patch, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/attributes/datetime/{request.Key}") .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) .Respond(TestConstants.AppJson, TestConstants.AttributeDatetimeResponse); // Act @@ -44,6 +45,7 @@ public async Task UpdateDatetimeAttribute_ShouldHandleException_WhenApiCallFails _mockHttp.Expect(HttpMethod.Patch, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/attributes/datetime/{request.Key}") .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); // Act @@ -68,6 +70,7 @@ public async Task UpdateDatetimeAttribute_ShouldReturnErrorResponse_WhenExceptio _mockHttp.Expect(HttpMethod.Patch, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/attributes/datetime/{request.Key}") .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) .Throw(new HttpRequestException("An error occurred")); // Act diff --git a/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.UpdateEmailAttribute.cs b/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.UpdateEmailAttribute.cs index 13b7d976..1029b6fc 100644 --- a/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.UpdateEmailAttribute.cs +++ b/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.UpdateEmailAttribute.cs @@ -21,6 +21,7 @@ public async Task UpdateEmailAttribute_ShouldReturnSuccess_WhenApiCallSucceeds() _mockHttp.Expect(HttpMethod.Patch, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/attributes/email/{request.Key}") .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) .Respond(TestConstants.AppJson, TestConstants.AttributeEmailResponse); // Act @@ -44,6 +45,7 @@ public async Task UpdateEmailAttribute_ShouldHandleException_WhenApiCallFails() _mockHttp.Expect(HttpMethod.Patch, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/attributes/email/{request.Key}") .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); // Act @@ -68,6 +70,7 @@ public async Task UpdateEmailAttribute_ShouldReturnErrorResponse_WhenExceptionOc _mockHttp.Expect(HttpMethod.Patch, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/attributes/email/{request.Key}") .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) .Throw(new HttpRequestException("An error occurred")); // Act diff --git a/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.UpdateEnumAttribute.cs b/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.UpdateEnumAttribute.cs index e2c9afaa..50a7207a 100644 --- a/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.UpdateEnumAttribute.cs +++ b/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.UpdateEnumAttribute.cs @@ -21,6 +21,7 @@ public async Task UpdateEnumAttribute_ShouldReturnSuccess_WhenApiCallSucceeds() _mockHttp.Expect(HttpMethod.Patch, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/attributes/enum/{request.Key}") .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) .Respond(TestConstants.AppJson, TestConstants.AttributeEnumResponse); // Act @@ -44,6 +45,7 @@ public async Task UpdateEnumAttribute_ShouldHandleException_WhenApiCallFails() _mockHttp.Expect(HttpMethod.Patch, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/attributes/enum/{request.Key}") .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); // Act @@ -68,6 +70,7 @@ public async Task UpdateEnumAttribute_ShouldReturnErrorResponse_WhenExceptionOcc _mockHttp.Expect(HttpMethod.Patch, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/attributes/enum/{request.Key}") .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) .Throw(new HttpRequestException("An error occurred")); // Act diff --git a/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.UpdateFloatAttribute.cs b/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.UpdateFloatAttribute.cs index 5add0254..16715f46 100644 --- a/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.UpdateFloatAttribute.cs +++ b/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.UpdateFloatAttribute.cs @@ -21,6 +21,7 @@ public async Task UpdateFloatAttribute_ShouldReturnSuccess_WhenApiCallSucceeds() _mockHttp.Expect(HttpMethod.Patch, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/attributes/float/{request.Key}") .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) .Respond(TestConstants.AppJson, TestConstants.AttributeFloatResponse); // Act @@ -44,6 +45,7 @@ public async Task UpdateFloatAttribute_ShouldHandleException_WhenApiCallFails() _mockHttp.Expect(HttpMethod.Patch, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/attributes/float/{request.Key}") .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); // Act @@ -68,6 +70,7 @@ public async Task UpdateFloatAttribute_ShouldReturnErrorResponse_WhenExceptionOc _mockHttp.Expect(HttpMethod.Patch, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/attributes/float/{request.Key}") .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) .Throw(new HttpRequestException("An error occurred")); // Act diff --git a/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.UpdateIntegerAttribute.cs b/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.UpdateIntegerAttribute.cs index 438e9658..c8e3f8ef 100644 --- a/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.UpdateIntegerAttribute.cs +++ b/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.UpdateIntegerAttribute.cs @@ -21,6 +21,7 @@ public async Task UpdateIntegerAttribute_ShouldReturnSuccess_WhenApiCallSucceeds _mockHttp.Expect(HttpMethod.Patch, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/attributes/integer/{request.Key}") .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) .Respond(TestConstants.AppJson, TestConstants.AttributeIntegerResponse); // Act @@ -44,6 +45,7 @@ public async Task UpdateIntegerAttribute_ShouldHandleException_WhenApiCallFails( _mockHttp.Expect(HttpMethod.Patch, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/attributes/integer/{request.Key}") .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); // Act @@ -68,6 +70,7 @@ public async Task UpdateIntegerAttribute_ShouldReturnErrorResponse_WhenException _mockHttp.Expect(HttpMethod.Patch, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/attributes/integer/{request.Key}") .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) .Throw(new HttpRequestException("An error occurred")); // Act diff --git a/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.UpdateIpAttribute.cs b/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.UpdateIpAttribute.cs index 8e41f535..36672906 100644 --- a/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.UpdateIpAttribute.cs +++ b/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.UpdateIpAttribute.cs @@ -21,6 +21,7 @@ public async Task UpdateIpAttribute_ShouldReturnSuccess_WhenApiCallSucceeds() _mockHttp.Expect(HttpMethod.Patch, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/attributes/ip/{request.Key}") .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) .Respond(TestConstants.AppJson, TestConstants.AttributeIpResponse); // Act @@ -44,6 +45,7 @@ public async Task UpdateIpAttribute_ShouldHandleException_WhenApiCallFails() _mockHttp.Expect(HttpMethod.Patch, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/attributes/ip/{request.Key}") .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); // Act @@ -68,6 +70,7 @@ public async Task UpdateIpAttribute_ShouldReturnErrorResponse_WhenExceptionOccur _mockHttp.Expect(HttpMethod.Patch, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/attributes/ip/{request.Key}") .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) .Throw(new HttpRequestException("An error occurred")); // Act diff --git a/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.UpdateRelationshipAttribute.cs b/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.UpdateRelationshipAttribute.cs index 30a2f89c..1f9becf0 100644 --- a/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.UpdateRelationshipAttribute.cs +++ b/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.UpdateRelationshipAttribute.cs @@ -21,6 +21,7 @@ public async Task UpdateRelationshipAttribute_ShouldReturnSuccess_WhenApiCallSuc _mockHttp.Expect(HttpMethod.Patch, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/attributes/{request.Key}/relationship") .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) .Respond(TestConstants.AppJson, TestConstants.AttributeRelationshipResponse); // Act @@ -44,6 +45,7 @@ public async Task UpdateRelationshipAttribute_ShouldHandleException_WhenApiCallF _mockHttp.Expect(HttpMethod.Patch, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/attributes/{request.Key}/relationship") .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); // Act @@ -68,6 +70,7 @@ public async Task UpdateRelationshipAttribute_ShouldReturnErrorResponse_WhenExce _mockHttp.Expect(HttpMethod.Patch, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/attributes/{request.Key}/relationship") .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) .Throw(new HttpRequestException("An error occurred")); // Act diff --git a/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.UpdateStringAttribute.cs b/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.UpdateStringAttribute.cs index 806f35fb..bedaeedc 100644 --- a/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.UpdateStringAttribute.cs +++ b/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.UpdateStringAttribute.cs @@ -21,6 +21,7 @@ public async Task UpdateStringAttribute_ShouldReturnSuccess_WhenApiCallSucceeds( _mockHttp.Expect(HttpMethod.Patch, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/attributes/string/{request.Key}") .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) .Respond(TestConstants.AppJson, TestConstants.AttributeStringResponse); // Act @@ -44,6 +45,7 @@ public async Task UpdateStringAttribute_ShouldHandleException_WhenApiCallFails() _mockHttp.Expect(HttpMethod.Patch, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/attributes/string/{request.Key}") .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); // Act @@ -68,6 +70,7 @@ public async Task UpdateStringAttribute_ShouldReturnErrorResponse_WhenExceptionO _mockHttp.Expect(HttpMethod.Patch, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/attributes/string/{request.Key}") .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) .Throw(new HttpRequestException("An error occurred")); // Act diff --git a/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.UpdateUrlAttribute.cs b/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.UpdateUrlAttribute.cs index 40fc3de3..a9738398 100644 --- a/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.UpdateUrlAttribute.cs +++ b/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.UpdateUrlAttribute.cs @@ -21,6 +21,7 @@ public async Task UpdateUrlAttribute_ShouldReturnSuccess_WhenApiCallSucceeds() _mockHttp.Expect(HttpMethod.Patch, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/attributes/url/{request.Key}") .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) .Respond(TestConstants.AppJson, TestConstants.AttributeUrlResponse); // Act @@ -44,6 +45,7 @@ public async Task UpdateUrlAttribute_ShouldHandleException_WhenApiCallFails() _mockHttp.Expect(HttpMethod.Patch, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/attributes/url/{request.Key}") .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); // Act @@ -68,6 +70,7 @@ public async Task UpdateUrlAttribute_ShouldReturnErrorResponse_WhenExceptionOccu _mockHttp.Expect(HttpMethod.Patch, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/attributes/url/{request.Key}") .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) .Throw(new HttpRequestException("An error occurred")); // Act From 3735cd4e764dc409f0ccfe8b483116fcd57b41c3 Mon Sep 17 00:00:00 2001 From: Matthew Parker Date: Tue, 10 Dec 2024 18:21:08 +0000 Subject: [PATCH 12/22] Implemented delete document --- .../Clients/DatabasesClient.cs | 17 +++++++++++-- .../Clients/IDatabasesClient.cs | 7 +++++- src/PinguApps.Appwrite.Playground/App.cs | 24 ++++++++----------- .../Clients/DatabasesClient.cs | 17 +++++++++++-- .../Clients/IDatabasesClient.cs | 7 +++++- 5 files changed, 52 insertions(+), 20 deletions(-) diff --git a/src/PinguApps.Appwrite.Client/Clients/DatabasesClient.cs b/src/PinguApps.Appwrite.Client/Clients/DatabasesClient.cs index 6dbdfcac..c9de8048 100644 --- a/src/PinguApps.Appwrite.Client/Clients/DatabasesClient.cs +++ b/src/PinguApps.Appwrite.Client/Clients/DatabasesClient.cs @@ -53,9 +53,22 @@ public async Task> CreateDocument(CreateDocumentRequest } } - [ExcludeFromCodeCoverage] /// - public Task DeleteDocument(DeleteDocumentRequest request) => throw new NotImplementedException(); + public async Task DeleteDocument(DeleteDocumentRequest request) + { + try + { + request.Validate(true); + + var result = await _databasesApi.DeleteDocument(GetCurrentSession(), request.DatabaseId, request.CollectionId, request.DocumentId); + + return result.GetApiResponse(); + } + catch (Exception e) + { + return e.GetExceptionResponse(); + } + } [ExcludeFromCodeCoverage] /// diff --git a/src/PinguApps.Appwrite.Client/Clients/IDatabasesClient.cs b/src/PinguApps.Appwrite.Client/Clients/IDatabasesClient.cs index 8bd83d51..c6217d38 100644 --- a/src/PinguApps.Appwrite.Client/Clients/IDatabasesClient.cs +++ b/src/PinguApps.Appwrite.Client/Clients/IDatabasesClient.cs @@ -31,7 +31,12 @@ public interface IDatabasesClient /// The document Task> CreateDocument(CreateDocumentRequest request); - [Obsolete("Endpoint not yet implemented.")] + /// + /// Delete a document by its unique ID. + /// Appwrite Docs + /// + /// The request content + /// 204 Success Code Task DeleteDocument(DeleteDocumentRequest request); [Obsolete("Endpoint not yet implemented.")] diff --git a/src/PinguApps.Appwrite.Playground/App.cs b/src/PinguApps.Appwrite.Playground/App.cs index 9cd1b4ad..e6ee200e 100644 --- a/src/PinguApps.Appwrite.Playground/App.cs +++ b/src/PinguApps.Appwrite.Playground/App.cs @@ -1,6 +1,5 @@ using Microsoft.Extensions.Configuration; using PinguApps.Appwrite.Shared.Requests.Databases; -using PinguApps.Appwrite.Shared.Utils; namespace PinguApps.Appwrite.Playground; internal class App @@ -18,17 +17,14 @@ public App(Client.IAppwriteClient client, Server.Clients.IAppwriteClient server, public async Task Run(string[] args) { - var request = CreateDocumentRequest.CreateBuilder() - .WithDatabaseId("67541a2800221703e717") - .WithCollectionId("67541a37001514b81821") - .WithData(new - { - test = "TEST", - boolAttribute = false - }) - .Build(); - - var serverResponse = await _server.Databases.CreateDocument(request); + var request = new DeleteDocumentRequest() + { + DatabaseId = "67541a2800221703e717", + CollectionId = "67541a37001514b81821", + DocumentId = "67587ff00029d437c8f3" + }; + + var serverResponse = await _server.Databases.DeleteDocument(request); Console.WriteLine(serverResponse.Result.Match( result => result.ToString(), @@ -37,9 +33,9 @@ public async Task Run(string[] args) Console.WriteLine("###############################################################################"); - request.DocumentId = IdUtils.GenerateUniqueId(); + request.DocumentId = "67587ff000057509d0ec"; - var clientResponse = await _client.Databases.CreateDocument(request); + var clientResponse = await _client.Databases.DeleteDocument(request); Console.WriteLine(clientResponse.Result.Match( result => result.ToString(), diff --git a/src/PinguApps.Appwrite.Server/Clients/DatabasesClient.cs b/src/PinguApps.Appwrite.Server/Clients/DatabasesClient.cs index 72953a1c..0cb5636d 100644 --- a/src/PinguApps.Appwrite.Server/Clients/DatabasesClient.cs +++ b/src/PinguApps.Appwrite.Server/Clients/DatabasesClient.cs @@ -616,9 +616,22 @@ public async Task> CreateDocument(CreateDocumentRequest } } - [ExcludeFromCodeCoverage] /// - public Task DeleteDocument(DeleteDocumentRequest request) => throw new NotImplementedException(); + public async Task DeleteDocument(DeleteDocumentRequest request) + { + try + { + request.Validate(true); + + var result = await _databasesApi.DeleteDocument(request.DatabaseId, request.CollectionId, request.DocumentId); + + return result.GetApiResponse(); + } + catch (Exception e) + { + return e.GetExceptionResponse(); + } + } [ExcludeFromCodeCoverage] /// diff --git a/src/PinguApps.Appwrite.Server/Clients/IDatabasesClient.cs b/src/PinguApps.Appwrite.Server/Clients/IDatabasesClient.cs index e5d43285..1c4f474e 100644 --- a/src/PinguApps.Appwrite.Server/Clients/IDatabasesClient.cs +++ b/src/PinguApps.Appwrite.Server/Clients/IDatabasesClient.cs @@ -298,7 +298,12 @@ public interface IDatabasesClient /// The document Task> CreateDocument(CreateDocumentRequest request); - [Obsolete("Endpoint not yet implemented.")] + /// + /// Delete a document by its unique ID. + /// Appwrite Docs + /// + /// The request content + /// 204 Success Code Task DeleteDocument(DeleteDocumentRequest request); [Obsolete("Endpoint not yet implemented.")] From 766d1173f703011a164c6cf0a86adb9285ab172b Mon Sep 17 00:00:00 2001 From: Matthew Parker Date: Tue, 10 Dec 2024 18:24:44 +0000 Subject: [PATCH 13/22] added tests for delete document --- .../DatabasesClientTests.DeleteDocument.cs | 78 +++++++++++++++++++ .../DatabasesClientTests.DeleteDocument.cs | 78 +++++++++++++++++++ 2 files changed, 156 insertions(+) create mode 100644 tests/PinguApps.Appwrite.Client.Tests/Clients/Databases/DatabasesClientTests.DeleteDocument.cs create mode 100644 tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.DeleteDocument.cs diff --git a/tests/PinguApps.Appwrite.Client.Tests/Clients/Databases/DatabasesClientTests.DeleteDocument.cs b/tests/PinguApps.Appwrite.Client.Tests/Clients/Databases/DatabasesClientTests.DeleteDocument.cs new file mode 100644 index 00000000..e713626b --- /dev/null +++ b/tests/PinguApps.Appwrite.Client.Tests/Clients/Databases/DatabasesClientTests.DeleteDocument.cs @@ -0,0 +1,78 @@ +using System.Net; +using PinguApps.Appwrite.Shared.Requests.Databases; +using PinguApps.Appwrite.Shared.Tests; +using PinguApps.Appwrite.Shared.Utils; +using RichardSzalay.MockHttp; + +namespace PinguApps.Appwrite.Client.Tests.Clients.Databases; +public partial class DatabasesClientTests +{ + [Fact] + public async Task DeleteDocument_ShouldReturnSuccess_WhenApiCallSucceeds() + { + // Arrange + var request = new DeleteDocumentRequest + { + DatabaseId = IdUtils.GenerateUniqueId(), + CollectionId = IdUtils.GenerateUniqueId(), + DocumentId = IdUtils.GenerateUniqueId() + }; + + _mockHttp.Expect(HttpMethod.Delete, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/documents/{request.DocumentId}") + .ExpectedHeaders() + .Respond(HttpStatusCode.NoContent); + + // Act + var result = await _appwriteClient.Databases.DeleteDocument(request); + + // Assert + Assert.True(result.Success); + } + + [Fact] + public async Task DeleteDocument_ShouldHandleException_WhenApiCallFails() + { + // Arrange + var request = new DeleteDocumentRequest + { + DatabaseId = IdUtils.GenerateUniqueId(), + CollectionId = IdUtils.GenerateUniqueId(), + DocumentId = IdUtils.GenerateUniqueId() + }; + + _mockHttp.Expect(HttpMethod.Delete, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/documents/{request.DocumentId}") + .ExpectedHeaders() + .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); + + // Act + var result = await _appwriteClient.Databases.DeleteDocument(request); + + // Assert + Assert.True(result.IsError); + Assert.True(result.IsAppwriteError); + } + + [Fact] + public async Task DeleteDocument_ShouldReturnErrorResponse_WhenExceptionOccurs() + { + // Arrange + var request = new DeleteDocumentRequest + { + DatabaseId = IdUtils.GenerateUniqueId(), + CollectionId = IdUtils.GenerateUniqueId(), + DocumentId = IdUtils.GenerateUniqueId() + }; + + _mockHttp.Expect(HttpMethod.Delete, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/documents/{request.DocumentId}") + .ExpectedHeaders() + .Throw(new HttpRequestException("An error occurred")); + + // Act + var result = await _appwriteClient.Databases.DeleteDocument(request); + + // Assert + Assert.False(result.Success); + Assert.True(result.IsInternalError); + Assert.Equal("An error occurred", result.Result.AsT2.Message); + } +} diff --git a/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.DeleteDocument.cs b/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.DeleteDocument.cs new file mode 100644 index 00000000..916b3cf9 --- /dev/null +++ b/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.DeleteDocument.cs @@ -0,0 +1,78 @@ +using System.Net; +using PinguApps.Appwrite.Shared.Requests.Databases; +using PinguApps.Appwrite.Shared.Tests; +using PinguApps.Appwrite.Shared.Utils; +using RichardSzalay.MockHttp; + +namespace PinguApps.Appwrite.Server.Tests.Clients.Databases; +public partial class DatabasesClientTests +{ + [Fact] + public async Task DeleteDocument_ShouldReturnSuccess_WhenApiCallSucceeds() + { + // Arrange + var request = new DeleteDocumentRequest + { + DatabaseId = IdUtils.GenerateUniqueId(), + CollectionId = IdUtils.GenerateUniqueId(), + DocumentId = IdUtils.GenerateUniqueId() + }; + + _mockHttp.Expect(HttpMethod.Delete, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/documents/{request.DocumentId}") + .ExpectedHeaders() + .Respond(HttpStatusCode.NoContent); + + // Act + var result = await _appwriteClient.Databases.DeleteDocument(request); + + // Assert + Assert.True(result.Success); + } + + [Fact] + public async Task DeleteDocument_ShouldHandleException_WhenApiCallFails() + { + // Arrange + var request = new DeleteDocumentRequest + { + DatabaseId = IdUtils.GenerateUniqueId(), + CollectionId = IdUtils.GenerateUniqueId(), + DocumentId = IdUtils.GenerateUniqueId() + }; + + _mockHttp.Expect(HttpMethod.Delete, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/documents/{request.DocumentId}") + .ExpectedHeaders() + .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); + + // Act + var result = await _appwriteClient.Databases.DeleteDocument(request); + + // Assert + Assert.True(result.IsError); + Assert.True(result.IsAppwriteError); + } + + [Fact] + public async Task DeleteDocument_ShouldReturnErrorResponse_WhenExceptionOccurs() + { + // Arrange + var request = new DeleteDocumentRequest + { + DatabaseId = IdUtils.GenerateUniqueId(), + CollectionId = IdUtils.GenerateUniqueId(), + DocumentId = IdUtils.GenerateUniqueId() + }; + + _mockHttp.Expect(HttpMethod.Delete, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/documents/{request.DocumentId}") + .ExpectedHeaders() + .Throw(new HttpRequestException("An error occurred")); + + // Act + var result = await _appwriteClient.Databases.DeleteDocument(request); + + // Assert + Assert.False(result.Success); + Assert.True(result.IsInternalError); + Assert.Equal("An error occurred", result.Result.AsT2.Message); + } +} From 599eb45f3e5bf464b2e03324cb7b84e24b97e87e Mon Sep 17 00:00:00 2001 From: Matthew Parker Date: Tue, 10 Dec 2024 18:47:46 +0000 Subject: [PATCH 14/22] Implemented GetDocument and made chances to support query limiting the document data --- .../Clients/DatabasesClient.cs | 17 ++++++++++++++-- .../Clients/IDatabasesClient.cs | 7 ++++++- src/PinguApps.Appwrite.Playground/App.cs | 11 +++++----- .../Clients/DatabasesClient.cs | 17 ++++++++++++++-- .../Clients/IDatabasesClient.cs | 9 +++++++-- .../Converters/DocumentConverter.cs | 20 +++++++++---------- .../Converters/DocumentGenericConverter.cs | 2 +- .../Responses/Document.cs | 4 ++-- .../Responses/DocumentBase.cs | 4 ++-- .../Responses/DocumentGeneric.cs | 4 ++-- 10 files changed, 66 insertions(+), 29 deletions(-) diff --git a/src/PinguApps.Appwrite.Client/Clients/DatabasesClient.cs b/src/PinguApps.Appwrite.Client/Clients/DatabasesClient.cs index c9de8048..9072af30 100644 --- a/src/PinguApps.Appwrite.Client/Clients/DatabasesClient.cs +++ b/src/PinguApps.Appwrite.Client/Clients/DatabasesClient.cs @@ -70,9 +70,22 @@ public async Task DeleteDocument(DeleteDocumentRequest request) } } - [ExcludeFromCodeCoverage] /// - public Task> GetDocument(GetDocumentRequest request) => throw new NotImplementedException(); + public async Task> GetDocument(GetDocumentRequest request) + { + try + { + request.Validate(true); + + var result = await _databasesApi.GetDocument(GetCurrentSession(), request.DatabaseId, request.CollectionId, request.DocumentId, RequestUtils.GetQueryStrings(request.Queries)); + + return result.GetApiResponse(); + } + catch (Exception e) + { + return e.GetExceptionResponse(); + } + } [ExcludeFromCodeCoverage] /// diff --git a/src/PinguApps.Appwrite.Client/Clients/IDatabasesClient.cs b/src/PinguApps.Appwrite.Client/Clients/IDatabasesClient.cs index c6217d38..890bf8d6 100644 --- a/src/PinguApps.Appwrite.Client/Clients/IDatabasesClient.cs +++ b/src/PinguApps.Appwrite.Client/Clients/IDatabasesClient.cs @@ -39,7 +39,12 @@ public interface IDatabasesClient /// 204 Success Code Task DeleteDocument(DeleteDocumentRequest request); - [Obsolete("Endpoint not yet implemented.")] + /// + /// Get a document by its unique ID. This endpoint response returns a JSON object with the document data. You can return select columns by passing in a Select query. + /// Appwrite Docs + /// + /// The request content + /// The document Task> GetDocument(GetDocumentRequest request); [Obsolete("Endpoint not yet implemented.")] diff --git a/src/PinguApps.Appwrite.Playground/App.cs b/src/PinguApps.Appwrite.Playground/App.cs index e6ee200e..4473909a 100644 --- a/src/PinguApps.Appwrite.Playground/App.cs +++ b/src/PinguApps.Appwrite.Playground/App.cs @@ -1,5 +1,6 @@ using Microsoft.Extensions.Configuration; using PinguApps.Appwrite.Shared.Requests.Databases; +using PinguApps.Appwrite.Shared.Utils; namespace PinguApps.Appwrite.Playground; internal class App @@ -17,14 +18,14 @@ public App(Client.IAppwriteClient client, Server.Clients.IAppwriteClient server, public async Task Run(string[] args) { - var request = new DeleteDocumentRequest() + var request = new GetDocumentRequest() { DatabaseId = "67541a2800221703e717", CollectionId = "67541a37001514b81821", - DocumentId = "67587ff00029d437c8f3" + DocumentId = "67541af9000055e59e59" }; - var serverResponse = await _server.Databases.DeleteDocument(request); + var serverResponse = await _server.Databases.GetDocument(request); Console.WriteLine(serverResponse.Result.Match( result => result.ToString(), @@ -33,9 +34,9 @@ public async Task Run(string[] args) Console.WriteLine("###############################################################################"); - request.DocumentId = "67587ff000057509d0ec"; + request.Queries = [Query.Select(["test"])]; - var clientResponse = await _client.Databases.DeleteDocument(request); + var clientResponse = await _client.Databases.GetDocument(request); Console.WriteLine(clientResponse.Result.Match( result => result.ToString(), diff --git a/src/PinguApps.Appwrite.Server/Clients/DatabasesClient.cs b/src/PinguApps.Appwrite.Server/Clients/DatabasesClient.cs index 0cb5636d..bcf9acfe 100644 --- a/src/PinguApps.Appwrite.Server/Clients/DatabasesClient.cs +++ b/src/PinguApps.Appwrite.Server/Clients/DatabasesClient.cs @@ -633,9 +633,22 @@ public async Task DeleteDocument(DeleteDocumentRequest request) } } - [ExcludeFromCodeCoverage] /// - public Task> GetDocument(GetDocumentRequest request) => throw new NotImplementedException(); + public async Task> GetDocument(GetDocumentRequest request) + { + try + { + request.Validate(true); + + var result = await _databasesApi.GetDocument(request.DatabaseId, request.CollectionId, request.DocumentId, RequestUtils.GetQueryStrings(request.Queries)); + + return result.GetApiResponse(); + } + catch (Exception e) + { + return e.GetExceptionResponse(); + } + } [ExcludeFromCodeCoverage] /// diff --git a/src/PinguApps.Appwrite.Server/Clients/IDatabasesClient.cs b/src/PinguApps.Appwrite.Server/Clients/IDatabasesClient.cs index 1c4f474e..ff687c2b 100644 --- a/src/PinguApps.Appwrite.Server/Clients/IDatabasesClient.cs +++ b/src/PinguApps.Appwrite.Server/Clients/IDatabasesClient.cs @@ -303,10 +303,15 @@ public interface IDatabasesClient /// Appwrite Docs /// /// The request content - /// 204 Success Code + /// 204 success code Task DeleteDocument(DeleteDocumentRequest request); - [Obsolete("Endpoint not yet implemented.")] + /// + /// Get a document by its unique ID. This endpoint response returns a JSON object with the document data. You can return select columns by passing in a Select query. + /// Appwrite Docs + /// + /// The request content + /// The document Task> GetDocument(GetDocumentRequest request); [Obsolete("Endpoint not yet implemented.")] diff --git a/src/PinguApps.Appwrite.Shared/Converters/DocumentConverter.cs b/src/PinguApps.Appwrite.Shared/Converters/DocumentConverter.cs index 0051db28..464b9e75 100644 --- a/src/PinguApps.Appwrite.Shared/Converters/DocumentConverter.cs +++ b/src/PinguApps.Appwrite.Shared/Converters/DocumentConverter.cs @@ -79,22 +79,22 @@ public class DocumentConverter : JsonConverter throw new JsonException("Unable to find a value for DatabaseId"); } - if (createdAt is null) - { - throw new JsonException("Unable to find a value for CreatedAt"); - } + //if (createdAt is null) + //{ + // throw new JsonException("Unable to find a value for CreatedAt"); + //} - if (updatedAt is null) - { - throw new JsonException("Unable to find a value for UpdatedAt"); - } + //if (updatedAt is null) + //{ + // throw new JsonException("Unable to find a value for UpdatedAt"); + //} if (permissions is null) { throw new JsonException("Unable to find a value for Permissions"); } - return new Document(id, collectionId, databaseId, createdAt.Value, updatedAt.Value, permissions, data); + return new Document(id, collectionId, databaseId, createdAt, updatedAt, permissions, data); } internal object? ReadValue(ref Utf8JsonReader reader, JsonSerializerOptions options) @@ -186,7 +186,7 @@ public override void Write(Utf8JsonWriter writer, Document value, JsonSerializer writer.WriteString("$databaseId", value.DatabaseId); // Use MultiFormatDateTimeConverter for DateTime properties - var dateTimeConverter = new MultiFormatDateTimeConverter(); + var dateTimeConverter = new NullableDateTimeConverter(); writer.WritePropertyName("$createdAt"); dateTimeConverter.Write(writer, value.CreatedAt, options); diff --git a/src/PinguApps.Appwrite.Shared/Converters/DocumentGenericConverter.cs b/src/PinguApps.Appwrite.Shared/Converters/DocumentGenericConverter.cs index b11a585d..ade68935 100644 --- a/src/PinguApps.Appwrite.Shared/Converters/DocumentGenericConverter.cs +++ b/src/PinguApps.Appwrite.Shared/Converters/DocumentGenericConverter.cs @@ -193,7 +193,7 @@ public override void Write(Utf8JsonWriter writer, Document value, JsonSer writer.WriteString("$databaseId", value.DatabaseId); // Use MultiFormatDateTimeConverter for DateTime properties - var dateTimeConverter = new MultiFormatDateTimeConverter(); + var dateTimeConverter = new NullableDateTimeConverter(); writer.WritePropertyName("$createdAt"); dateTimeConverter.Write(writer, value.CreatedAt, options); diff --git a/src/PinguApps.Appwrite.Shared/Responses/Document.cs b/src/PinguApps.Appwrite.Shared/Responses/Document.cs index 0723c37b..ad18c6c5 100644 --- a/src/PinguApps.Appwrite.Shared/Responses/Document.cs +++ b/src/PinguApps.Appwrite.Shared/Responses/Document.cs @@ -22,8 +22,8 @@ public record Document( string Id, string CollectionId, string DatabaseId, - DateTime CreatedAt, - DateTime UpdatedAt, + DateTime? CreatedAt, + DateTime? UpdatedAt, IReadOnlyList Permissions, [property: JsonExtensionData] Dictionary Data ) : DocumentBase(Id, CollectionId, DatabaseId, CreatedAt, UpdatedAt, Permissions) diff --git a/src/PinguApps.Appwrite.Shared/Responses/DocumentBase.cs b/src/PinguApps.Appwrite.Shared/Responses/DocumentBase.cs index 15ea69c7..d48a5395 100644 --- a/src/PinguApps.Appwrite.Shared/Responses/DocumentBase.cs +++ b/src/PinguApps.Appwrite.Shared/Responses/DocumentBase.cs @@ -20,7 +20,7 @@ public abstract record DocumentBase( [property: JsonPropertyName("$id")] string Id, [property: JsonPropertyName("$collectionId")] string CollectionId, [property: JsonPropertyName("$databaseId")] string DatabaseId, - [property: JsonPropertyName("$createdAt"), JsonConverter(typeof(MultiFormatDateTimeConverter))] DateTime CreatedAt, - [property: JsonPropertyName("$updatedAt"), JsonConverter(typeof(MultiFormatDateTimeConverter))] DateTime UpdatedAt, + [property: JsonPropertyName("$createdAt"), JsonConverter(typeof(NullableDateTimeConverter))] DateTime? CreatedAt, + [property: JsonPropertyName("$updatedAt"), JsonConverter(typeof(NullableDateTimeConverter))] DateTime? UpdatedAt, [property: JsonPropertyName("$permissions"), JsonConverter(typeof(PermissionReadOnlyListConverter))] IReadOnlyList Permissions ); diff --git a/src/PinguApps.Appwrite.Shared/Responses/DocumentGeneric.cs b/src/PinguApps.Appwrite.Shared/Responses/DocumentGeneric.cs index e5465118..09dbe6be 100644 --- a/src/PinguApps.Appwrite.Shared/Responses/DocumentGeneric.cs +++ b/src/PinguApps.Appwrite.Shared/Responses/DocumentGeneric.cs @@ -21,8 +21,8 @@ public record Document( string Id, string CollectionId, string DatabaseId, - DateTime CreatedAt, - DateTime UpdatedAt, + DateTime? CreatedAt, + DateTime? UpdatedAt, IReadOnlyList Permissions, TData Data ) : DocumentBase(Id, CollectionId, DatabaseId, CreatedAt, UpdatedAt, Permissions) From 7c5b7614d55050b9fc54ca3159a770f6abb6d577 Mon Sep 17 00:00:00 2001 From: Matthew Parker Date: Tue, 10 Dec 2024 18:50:36 +0000 Subject: [PATCH 15/22] Fixed failing tests for Document --- .../Converters/DocumentConverter.cs | 10 ------- .../Converters/DocumentConverterTests.cs | 30 ------------------- .../Responses/DocumentTests.cs | 4 +-- .../Responses/DocumentsListTests.cs | 4 +-- 4 files changed, 4 insertions(+), 44 deletions(-) diff --git a/src/PinguApps.Appwrite.Shared/Converters/DocumentConverter.cs b/src/PinguApps.Appwrite.Shared/Converters/DocumentConverter.cs index 464b9e75..f7e40cac 100644 --- a/src/PinguApps.Appwrite.Shared/Converters/DocumentConverter.cs +++ b/src/PinguApps.Appwrite.Shared/Converters/DocumentConverter.cs @@ -79,16 +79,6 @@ public class DocumentConverter : JsonConverter throw new JsonException("Unable to find a value for DatabaseId"); } - //if (createdAt is null) - //{ - // throw new JsonException("Unable to find a value for CreatedAt"); - //} - - //if (updatedAt is null) - //{ - // throw new JsonException("Unable to find a value for UpdatedAt"); - //} - if (permissions is null) { throw new JsonException("Unable to find a value for Permissions"); diff --git a/tests/PinguApps.Appwrite.Shared.Tests/Converters/DocumentConverterTests.cs b/tests/PinguApps.Appwrite.Shared.Tests/Converters/DocumentConverterTests.cs index 676f37f4..c8cbdc18 100644 --- a/tests/PinguApps.Appwrite.Shared.Tests/Converters/DocumentConverterTests.cs +++ b/tests/PinguApps.Appwrite.Shared.Tests/Converters/DocumentConverterTests.cs @@ -243,36 +243,6 @@ public void Read_MissingDatabaseId_ThrowsJsonException() Assert.Throws(() => JsonSerializer.Deserialize(json, _options)); } - [Fact] - public void Read_MissingCreatedAt_ThrowsJsonException() - { - var json = @" - { - ""$id"": ""1"", - ""$collectionId"": ""col1"", - ""$databaseId"": ""db1"", - ""$updatedAt"": ""2020-10-15T06:38:00.000+00:00"", - ""$permissions"": [""read(\""any\"")""] - }"; - - Assert.Throws(() => JsonSerializer.Deserialize(json, _options)); - } - - [Fact] - public void Read_MissingUpdatedAt_ThrowsJsonException() - { - var json = @" - { - ""$id"": ""1"", - ""$collectionId"": ""col1"", - ""$databaseId"": ""db1"", - ""$createdAt"": ""2020-10-15T06:38:00.000+00:00"", - ""$permissions"": [""read(\""any\"")""] - }"; - - Assert.Throws(() => JsonSerializer.Deserialize(json, _options)); - } - [Fact] public void Read_MissingPermissions_ThrowsJsonException() { diff --git a/tests/PinguApps.Appwrite.Shared.Tests/Responses/DocumentTests.cs b/tests/PinguApps.Appwrite.Shared.Tests/Responses/DocumentTests.cs index 2ccae015..555f5bb7 100644 --- a/tests/PinguApps.Appwrite.Shared.Tests/Responses/DocumentTests.cs +++ b/tests/PinguApps.Appwrite.Shared.Tests/Responses/DocumentTests.cs @@ -14,8 +14,8 @@ public void Document_ShouldBeDeserialized_FromJson() Assert.Equal("5e5ea5c16897e", document.Id); Assert.Equal("5e5ea5c15117e", document.CollectionId); Assert.Equal("5e5ea5c15117e", document.DatabaseId); - Assert.Equal(DateTime.Parse("2020-10-15T06:38:00.000+00:00").ToUniversalTime(), document.CreatedAt.ToUniversalTime()); - Assert.Equal(DateTime.Parse("2020-10-15T06:38:00.000+00:00").ToUniversalTime(), document.UpdatedAt.ToUniversalTime()); + Assert.Equal(DateTime.Parse("2020-10-15T06:38:00.000+00:00").ToUniversalTime(), document.CreatedAt?.ToUniversalTime()); + Assert.Equal(DateTime.Parse("2020-10-15T06:38:00.000+00:00").ToUniversalTime(), document.UpdatedAt?.ToUniversalTime()); Assert.Single(document.Permissions); Assert.Equal(PermissionType.Read, document.Permissions[0].PermissionType); Assert.Equal(RoleType.Any, document.Permissions[0].RoleType); diff --git a/tests/PinguApps.Appwrite.Shared.Tests/Responses/DocumentsListTests.cs b/tests/PinguApps.Appwrite.Shared.Tests/Responses/DocumentsListTests.cs index b8f38dbc..a9e5e297 100644 --- a/tests/PinguApps.Appwrite.Shared.Tests/Responses/DocumentsListTests.cs +++ b/tests/PinguApps.Appwrite.Shared.Tests/Responses/DocumentsListTests.cs @@ -42,8 +42,8 @@ public void CanBeDeserialized_FromJson() Assert.Equal("5e5ea5c16897e", document.Id); Assert.Equal("5e5ea5c15117e", document.CollectionId); Assert.Equal("5e5ea5c15117e", document.DatabaseId); - Assert.Equal(DateTime.Parse("2020-10-15T06:38:00.000+00:00").ToUniversalTime(), document.CreatedAt.ToUniversalTime()); - Assert.Equal(DateTime.Parse("2020-10-15T06:38:00.000+00:00").ToUniversalTime(), document.UpdatedAt.ToUniversalTime()); + Assert.Equal(DateTime.Parse("2020-10-15T06:38:00.000+00:00").ToUniversalTime(), document.CreatedAt?.ToUniversalTime()); + Assert.Equal(DateTime.Parse("2020-10-15T06:38:00.000+00:00").ToUniversalTime(), document.UpdatedAt?.ToUniversalTime()); Assert.Single(document.Permissions); Assert.Equal(PermissionType.Read, document.Permissions[0].PermissionType); Assert.Equal(RoleType.Any, document.Permissions[0].RoleType); From dc6d9cd4dab6a9f7c41f501f4b8b85f5acc7bd99 Mon Sep 17 00:00:00 2001 From: Matthew Parker Date: Tue, 10 Dec 2024 18:59:09 +0000 Subject: [PATCH 16/22] added tests for get document --- .../DatabasesClientTests.GetDocument.cs | 103 ++++++++++++++++++ .../DatabasesClientTests.GetDocument.cs | 103 ++++++++++++++++++ 2 files changed, 206 insertions(+) create mode 100644 tests/PinguApps.Appwrite.Client.Tests/Clients/Databases/DatabasesClientTests.GetDocument.cs create mode 100644 tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.GetDocument.cs diff --git a/tests/PinguApps.Appwrite.Client.Tests/Clients/Databases/DatabasesClientTests.GetDocument.cs b/tests/PinguApps.Appwrite.Client.Tests/Clients/Databases/DatabasesClientTests.GetDocument.cs new file mode 100644 index 00000000..131e41eb --- /dev/null +++ b/tests/PinguApps.Appwrite.Client.Tests/Clients/Databases/DatabasesClientTests.GetDocument.cs @@ -0,0 +1,103 @@ +using System.Net; +using PinguApps.Appwrite.Shared.Requests.Databases; +using PinguApps.Appwrite.Shared.Tests; +using PinguApps.Appwrite.Shared.Utils; +using RichardSzalay.MockHttp; + +namespace PinguApps.Appwrite.Client.Tests.Clients.Databases; +public partial class DatabasesClientTests +{ + [Fact] + public async Task GetDocument_ShouldReturnSuccess_WhenApiCallSucceeds() + { + // Arrange + var request = new GetDocumentRequest + { + DatabaseId = IdUtils.GenerateUniqueId(), + CollectionId = IdUtils.GenerateUniqueId(), + DocumentId = IdUtils.GenerateUniqueId(), + }; + + _mockHttp.Expect(HttpMethod.Get, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/documents/{request.DocumentId}") + .ExpectedHeaders() + .Respond(TestConstants.AppJson, TestConstants.DocumentResponse); + + // Act + var result = await _appwriteClient.Databases.GetDocument(request); + + // Assert + Assert.True(result.Success); + } + + [Fact] + public async Task GetDocument_ShouldProvideQueryParams_WhenQueriesProvided() + { + // Arrange + var query = Query.Select(["col1", "col2"]); + var request = new GetDocumentRequest + { + DatabaseId = IdUtils.GenerateUniqueId(), + CollectionId = IdUtils.GenerateUniqueId(), + DocumentId = IdUtils.GenerateUniqueId(), + Queries = [query] + }; + + _mockHttp.Expect(HttpMethod.Get, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/documents/{request.DocumentId}") + .ExpectedHeaders() + .WithQueryString($"queries[]={query.GetQueryString()}") + .Respond(TestConstants.AppJson, TestConstants.DocumentResponse); + + // Act + var result = await _appwriteClient.Databases.GetDocument(request); + + // Assert + Assert.True(result.Success); + } + + [Fact] + public async Task GetDocument_ShouldHandleException_WhenApiCallFails() + { + // Arrange + var request = new GetDocumentRequest + { + DatabaseId = IdUtils.GenerateUniqueId(), + CollectionId = IdUtils.GenerateUniqueId(), + DocumentId = IdUtils.GenerateUniqueId(), + }; + + _mockHttp.Expect(HttpMethod.Get, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/documents/{request.DocumentId}") + .ExpectedHeaders() + .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); + + // Act + var result = await _appwriteClient.Databases.GetDocument(request); + + // Assert + Assert.True(result.IsError); + Assert.True(result.IsAppwriteError); + } + + [Fact] + public async Task GetDocument_ShouldReturnErrorResponse_WhenExceptionOccurs() + { + // Arrange + var request = new GetDocumentRequest + { + DatabaseId = IdUtils.GenerateUniqueId(), + CollectionId = IdUtils.GenerateUniqueId(), + DocumentId = IdUtils.GenerateUniqueId(), + }; + + _mockHttp.Expect(HttpMethod.Get, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/documents/{request.DocumentId}") + .ExpectedHeaders() + .Throw(new HttpRequestException("An error occurred")); + + // Act + var result = await _appwriteClient.Databases.GetDocument(request); + + // Assert + Assert.False(result.Success); + Assert.True(result.IsInternalError); + Assert.Equal("An error occurred", result.Result.AsT2.Message); + } +} diff --git a/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.GetDocument.cs b/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.GetDocument.cs new file mode 100644 index 00000000..4a030cf8 --- /dev/null +++ b/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.GetDocument.cs @@ -0,0 +1,103 @@ +using System.Net; +using PinguApps.Appwrite.Shared.Requests.Databases; +using PinguApps.Appwrite.Shared.Tests; +using PinguApps.Appwrite.Shared.Utils; +using RichardSzalay.MockHttp; + +namespace PinguApps.Appwrite.Server.Tests.Clients.Databases; +public partial class DatabasesClientTests +{ + [Fact] + public async Task GetDocument_ShouldReturnSuccess_WhenApiCallSucceeds() + { + // Arrange + var request = new GetDocumentRequest + { + DatabaseId = IdUtils.GenerateUniqueId(), + CollectionId = IdUtils.GenerateUniqueId(), + DocumentId = IdUtils.GenerateUniqueId(), + }; + + _mockHttp.Expect(HttpMethod.Get, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/documents/{request.DocumentId}") + .ExpectedHeaders() + .Respond(TestConstants.AppJson, TestConstants.DocumentResponse); + + // Act + var result = await _appwriteClient.Databases.GetDocument(request); + + // Assert + Assert.True(result.Success); + } + + [Fact] + public async Task GetDocument_ShouldProvideQueryParams_WhenQueriesProvided() + { + // Arrange + var query = Query.Select(["col1", "col2"]); + var request = new GetDocumentRequest + { + DatabaseId = IdUtils.GenerateUniqueId(), + CollectionId = IdUtils.GenerateUniqueId(), + DocumentId = IdUtils.GenerateUniqueId(), + Queries = [query] + }; + + _mockHttp.Expect(HttpMethod.Get, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/documents/{request.DocumentId}") + .ExpectedHeaders() + .WithQueryString($"queries[]={query.GetQueryString()}") + .Respond(TestConstants.AppJson, TestConstants.DocumentResponse); + + // Act + var result = await _appwriteClient.Databases.GetDocument(request); + + // Assert + Assert.True(result.Success); + } + + [Fact] + public async Task GetDocument_ShouldHandleException_WhenApiCallFails() + { + // Arrange + var request = new GetDocumentRequest + { + DatabaseId = IdUtils.GenerateUniqueId(), + CollectionId = IdUtils.GenerateUniqueId(), + DocumentId = IdUtils.GenerateUniqueId(), + }; + + _mockHttp.Expect(HttpMethod.Get, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/documents/{request.DocumentId}") + .ExpectedHeaders() + .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); + + // Act + var result = await _appwriteClient.Databases.GetDocument(request); + + // Assert + Assert.True(result.IsError); + Assert.True(result.IsAppwriteError); + } + + [Fact] + public async Task GetDocument_ShouldReturnErrorResponse_WhenExceptionOccurs() + { + // Arrange + var request = new GetDocumentRequest + { + DatabaseId = IdUtils.GenerateUniqueId(), + CollectionId = IdUtils.GenerateUniqueId(), + DocumentId = IdUtils.GenerateUniqueId(), + }; + + _mockHttp.Expect(HttpMethod.Get, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/documents/{request.DocumentId}") + .ExpectedHeaders() + .Throw(new HttpRequestException("An error occurred")); + + // Act + var result = await _appwriteClient.Databases.GetDocument(request); + + // Assert + Assert.False(result.Success); + Assert.True(result.IsInternalError); + Assert.Equal("An error occurred", result.Result.AsT2.Message); + } +} From 0041e2b4b0de6144078f3e763864d7adac160d6b Mon Sep 17 00:00:00 2001 From: Matthew Parker Date: Tue, 10 Dec 2024 19:00:51 +0000 Subject: [PATCH 17/22] Removed unused variable from some tests --- .../Databases/DatabasesClientTests.ListAttributes.cs | 5 ----- .../Databases/DatabasesClientTests.ListCollections.cs | 6 ------ .../Clients/Databases/DatabasesClientTests.ListDatabases.cs | 6 ------ 3 files changed, 17 deletions(-) diff --git a/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.ListAttributes.cs b/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.ListAttributes.cs index 23ad8386..fa60a459 100644 --- a/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.ListAttributes.cs +++ b/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.ListAttributes.cs @@ -40,11 +40,6 @@ public async Task ListAttributes_ShouldProvideQueryParams_WhenQueriesProvided() Queries = new List { query } }; - var expectedQueryParams = new Dictionary - { - { "queries[]", query.GetQueryString() } - }; - _mockHttp.Expect(HttpMethod.Get, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/attributes") .ExpectedHeaders() .WithQueryString($"queries[]={query.GetQueryString()}") diff --git a/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.ListCollections.cs b/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.ListCollections.cs index 1b51cc02..27410f0d 100644 --- a/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.ListCollections.cs +++ b/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.ListCollections.cs @@ -40,12 +40,6 @@ public async Task ListCollections_ShouldProvideQueryParams_WhenQueriesAndSearchP Search = search }; - var expectedQueryParams = new Dictionary - { - { "queries[]", query.GetQueryString() }, - { "search", search } - }; - _mockHttp.Expect(HttpMethod.Get, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections") .ExpectedHeaders() .WithQueryString($"queries[]={query.GetQueryString()}&search={search}") diff --git a/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.ListDatabases.cs b/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.ListDatabases.cs index 390a9942..67bcf65a 100644 --- a/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.ListDatabases.cs +++ b/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.ListDatabases.cs @@ -36,12 +36,6 @@ public async Task ListDatabases_ShouldProvideQueryParams_WhenQueriesAndSearchPro Search = search }; - var expectedQueryParams = new Dictionary - { - { "queries[]", query.GetQueryString() }, - { "search", search } - }; - _mockHttp.Expect(HttpMethod.Get, $"{TestConstants.Endpoint}/databases") .ExpectedHeaders() .WithQueryString($"queries[]={query.GetQueryString()}&search={search}") From 8a282db3ce3e880d88697af9342a91d10215afdc Mon Sep 17 00:00:00 2001 From: Matthew Parker Date: Tue, 10 Dec 2024 19:06:18 +0000 Subject: [PATCH 18/22] Implemented Update Document --- .../Clients/DatabasesClient.cs | 18 ++++++++++++++--- .../Clients/IDatabasesClient.cs | 10 +++++++--- src/PinguApps.Appwrite.Playground/App.cs | 20 +++++++++---------- .../Clients/DatabasesClient.cs | 18 ++++++++++++++--- .../Clients/IDatabasesClient.cs | 10 +++++++--- 5 files changed, 54 insertions(+), 22 deletions(-) diff --git a/src/PinguApps.Appwrite.Client/Clients/DatabasesClient.cs b/src/PinguApps.Appwrite.Client/Clients/DatabasesClient.cs index 9072af30..ba81c4df 100644 --- a/src/PinguApps.Appwrite.Client/Clients/DatabasesClient.cs +++ b/src/PinguApps.Appwrite.Client/Clients/DatabasesClient.cs @@ -1,5 +1,4 @@ using System; -using System.Diagnostics.CodeAnalysis; using System.Threading.Tasks; using PinguApps.Appwrite.Client.Internals; using PinguApps.Appwrite.Client.Utils; @@ -87,7 +86,20 @@ public async Task> GetDocument(GetDocumentRequest reque } } - [ExcludeFromCodeCoverage] /// - public Task> UpdateDocument(UpdateDocumentRequest request) => throw new NotImplementedException(); + public async Task> UpdateDocument(UpdateDocumentRequest request) + { + try + { + request.Validate(true); + + var result = await _databasesApi.UpdateDocument(GetCurrentSession(), request.DatabaseId, request.CollectionId, request.DocumentId, request); + + return result.GetApiResponse(); + } + catch (Exception e) + { + return e.GetExceptionResponse(); + } + } } diff --git a/src/PinguApps.Appwrite.Client/Clients/IDatabasesClient.cs b/src/PinguApps.Appwrite.Client/Clients/IDatabasesClient.cs index 890bf8d6..bf5797fc 100644 --- a/src/PinguApps.Appwrite.Client/Clients/IDatabasesClient.cs +++ b/src/PinguApps.Appwrite.Client/Clients/IDatabasesClient.cs @@ -1,5 +1,4 @@ -using System; -using System.Threading.Tasks; +using System.Threading.Tasks; using PinguApps.Appwrite.Shared; using PinguApps.Appwrite.Shared.Requests.Databases; using PinguApps.Appwrite.Shared.Responses; @@ -47,6 +46,11 @@ public interface IDatabasesClient /// The document Task> GetDocument(GetDocumentRequest request); - [Obsolete("Endpoint not yet implemented.")] + /// + /// Update a document by its unique ID. Using the patch method you can pass only specific fields that will get updated. + /// Appwrite Docs + /// + /// The request content + /// The document Task> UpdateDocument(UpdateDocumentRequest request); } diff --git a/src/PinguApps.Appwrite.Playground/App.cs b/src/PinguApps.Appwrite.Playground/App.cs index 4473909a..ff32aba6 100644 --- a/src/PinguApps.Appwrite.Playground/App.cs +++ b/src/PinguApps.Appwrite.Playground/App.cs @@ -1,6 +1,5 @@ using Microsoft.Extensions.Configuration; using PinguApps.Appwrite.Shared.Requests.Databases; -using PinguApps.Appwrite.Shared.Utils; namespace PinguApps.Appwrite.Playground; internal class App @@ -18,14 +17,14 @@ public App(Client.IAppwriteClient client, Server.Clients.IAppwriteClient server, public async Task Run(string[] args) { - var request = new GetDocumentRequest() - { - DatabaseId = "67541a2800221703e717", - CollectionId = "67541a37001514b81821", - DocumentId = "67541af9000055e59e59" - }; + var request = UpdateDocumentRequest.CreateBuilder() + .WithDatabaseId("67541a2800221703e717") + .WithCollectionId("67541a37001514b81821") + .WithDocumentId("67541af9000055e59e59") + .AddField("test", "Server Update") + .Build(); - var serverResponse = await _server.Databases.GetDocument(request); + var serverResponse = await _server.Databases.UpdateDocument(request); Console.WriteLine(serverResponse.Result.Match( result => result.ToString(), @@ -34,9 +33,10 @@ public async Task Run(string[] args) Console.WriteLine("###############################################################################"); - request.Queries = [Query.Select(["test"])]; + Console.ReadKey(); + request.Data["test"] = "Client Update"; - var clientResponse = await _client.Databases.GetDocument(request); + var clientResponse = await _client.Databases.UpdateDocument(request); Console.WriteLine(clientResponse.Result.Match( result => result.ToString(), diff --git a/src/PinguApps.Appwrite.Server/Clients/DatabasesClient.cs b/src/PinguApps.Appwrite.Server/Clients/DatabasesClient.cs index bcf9acfe..1a47a2ca 100644 --- a/src/PinguApps.Appwrite.Server/Clients/DatabasesClient.cs +++ b/src/PinguApps.Appwrite.Server/Clients/DatabasesClient.cs @@ -1,5 +1,4 @@ using System; -using System.Diagnostics.CodeAnalysis; using System.Threading.Tasks; using PinguApps.Appwrite.Server.Internals; using PinguApps.Appwrite.Server.Utils; @@ -650,9 +649,22 @@ public async Task> GetDocument(GetDocumentRequest reque } } - [ExcludeFromCodeCoverage] /// - public Task> UpdateDocument(UpdateDocumentRequest request) => throw new NotImplementedException(); + public async Task> UpdateDocument(UpdateDocumentRequest request) + { + try + { + request.Validate(true); + + var result = await _databasesApi.UpdateDocument(request.DatabaseId, request.CollectionId, request.DocumentId, request); + + return result.GetApiResponse(); + } + catch (Exception e) + { + return e.GetExceptionResponse(); + } + } /// public async Task> ListIndexes(ListIndexesRequest request) diff --git a/src/PinguApps.Appwrite.Server/Clients/IDatabasesClient.cs b/src/PinguApps.Appwrite.Server/Clients/IDatabasesClient.cs index ff687c2b..9cc432c9 100644 --- a/src/PinguApps.Appwrite.Server/Clients/IDatabasesClient.cs +++ b/src/PinguApps.Appwrite.Server/Clients/IDatabasesClient.cs @@ -1,5 +1,4 @@ -using System; -using System.Threading.Tasks; +using System.Threading.Tasks; using PinguApps.Appwrite.Shared; using PinguApps.Appwrite.Shared.Enums; using PinguApps.Appwrite.Shared.Requests.Databases; @@ -314,7 +313,12 @@ public interface IDatabasesClient /// The document Task> GetDocument(GetDocumentRequest request); - [Obsolete("Endpoint not yet implemented.")] + /// + /// Update a document by its unique ID. Using the patch method you can pass only specific fields that will get updated. + /// Appwrite Docs + /// + /// The request content + /// The document Task> UpdateDocument(UpdateDocumentRequest request); /// From 0c869087b58ae8e26572cee4401d8451f6450cf2 Mon Sep 17 00:00:00 2001 From: Matthew Parker Date: Tue, 10 Dec 2024 19:15:16 +0000 Subject: [PATCH 19/22] Testing the before / after builder pattern for update document --- src/PinguApps.Appwrite.Playground/App.cs | 31 +++++++++++++++++------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/src/PinguApps.Appwrite.Playground/App.cs b/src/PinguApps.Appwrite.Playground/App.cs index ff32aba6..6bcb8df0 100644 --- a/src/PinguApps.Appwrite.Playground/App.cs +++ b/src/PinguApps.Appwrite.Playground/App.cs @@ -1,4 +1,5 @@ -using Microsoft.Extensions.Configuration; +using System.Text.Json.Serialization; +using Microsoft.Extensions.Configuration; using PinguApps.Appwrite.Shared.Requests.Databases; namespace PinguApps.Appwrite.Playground; @@ -15,13 +16,25 @@ public App(Client.IAppwriteClient client, Server.Clients.IAppwriteClient server, _session = config.GetValue("Session"); } + private class Rec + { + [JsonPropertyName("test")] + public string Test { get; set; } = string.Empty; + + [JsonPropertyName("boolAttribute")] + public bool BoolAttribute { get; set; } + } + public async Task Run(string[] args) { + var before = new Rec { Test = "test", BoolAttribute = false }; + var after = new Rec { Test = "test", BoolAttribute = true }; + var request = UpdateDocumentRequest.CreateBuilder() .WithDatabaseId("67541a2800221703e717") .WithCollectionId("67541a37001514b81821") .WithDocumentId("67541af9000055e59e59") - .AddField("test", "Server Update") + .WithChanges(before, after) .Build(); var serverResponse = await _server.Databases.UpdateDocument(request); @@ -33,14 +46,14 @@ public async Task Run(string[] args) Console.WriteLine("###############################################################################"); - Console.ReadKey(); - request.Data["test"] = "Client Update"; + //Console.ReadKey(); + //request.Data["test"] = "Client Update"; - var clientResponse = await _client.Databases.UpdateDocument(request); + //var clientResponse = await _client.Databases.UpdateDocument(request); - Console.WriteLine(clientResponse.Result.Match( - result => result.ToString(), - appwriteError => appwriteError.Message, - internalError => internalError.Message)); + //Console.WriteLine(clientResponse.Result.Match( + // result => result.ToString(), + // appwriteError => appwriteError.Message, + // internalError => internalError.Message)); } } From 0f600e8181bacfbfab40f98118475bd2ad760822 Mon Sep 17 00:00:00 2001 From: Matthew Parker Date: Tue, 10 Dec 2024 19:20:15 +0000 Subject: [PATCH 20/22] added tests for update document --- .../DatabasesClientTests.UpdateDocument.cs | 78 +++++++++++++++++++ .../DatabasesClientTests.UpdateDocument.cs | 78 +++++++++++++++++++ 2 files changed, 156 insertions(+) create mode 100644 tests/PinguApps.Appwrite.Client.Tests/Clients/Databases/DatabasesClientTests.UpdateDocument.cs create mode 100644 tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.UpdateDocument.cs diff --git a/tests/PinguApps.Appwrite.Client.Tests/Clients/Databases/DatabasesClientTests.UpdateDocument.cs b/tests/PinguApps.Appwrite.Client.Tests/Clients/Databases/DatabasesClientTests.UpdateDocument.cs new file mode 100644 index 00000000..7cd92fac --- /dev/null +++ b/tests/PinguApps.Appwrite.Client.Tests/Clients/Databases/DatabasesClientTests.UpdateDocument.cs @@ -0,0 +1,78 @@ +using System.Net; +using PinguApps.Appwrite.Shared.Requests.Databases; +using PinguApps.Appwrite.Shared.Tests; +using PinguApps.Appwrite.Shared.Utils; +using RichardSzalay.MockHttp; + +namespace PinguApps.Appwrite.Client.Tests.Clients.Databases; +public partial class DatabasesClientTests +{ + [Fact] + public async Task UpdateDocument_ShouldReturnSuccess_WhenApiCallSucceeds() + { + // Arrange + var request = UpdateDocumentRequest.CreateBuilder() + .WithDatabaseId(IdUtils.GenerateUniqueId()) + .WithCollectionId(IdUtils.GenerateUniqueId()) + .WithDocumentId(IdUtils.GenerateUniqueId()) + .AddField("test", "test") + .Build(); + + _mockHttp.Expect(HttpMethod.Patch, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/documents/{request.DocumentId}") + .ExpectedHeaders() + .Respond(TestConstants.AppJson, TestConstants.DocumentResponse); + + // Act + var result = await _appwriteClient.Databases.UpdateDocument(request); + + // Assert + Assert.True(result.Success); + } + + [Fact] + public async Task UpdateDocument_ShouldHandleException_WhenApiCallFails() + { + // Arrange + var request = UpdateDocumentRequest.CreateBuilder() + .WithDatabaseId(IdUtils.GenerateUniqueId()) + .WithCollectionId(IdUtils.GenerateUniqueId()) + .WithDocumentId(IdUtils.GenerateUniqueId()) + .AddField("test", "test") + .Build(); + + _mockHttp.Expect(HttpMethod.Patch, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/documents/{request.DocumentId}") + .ExpectedHeaders() + .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); + + // Act + var result = await _appwriteClient.Databases.UpdateDocument(request); + + // Assert + Assert.True(result.IsError); + Assert.True(result.IsAppwriteError); + } + + [Fact] + public async Task UpdateDocument_ShouldReturnErrorResponse_WhenExceptionOccurs() + { + // Arrange + var request = UpdateDocumentRequest.CreateBuilder() + .WithDatabaseId(IdUtils.GenerateUniqueId()) + .WithCollectionId(IdUtils.GenerateUniqueId()) + .WithDocumentId(IdUtils.GenerateUniqueId()) + .AddField("test", "test") + .Build(); + + _mockHttp.Expect(HttpMethod.Patch, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/documents/{request.DocumentId}") + .ExpectedHeaders() + .Throw(new HttpRequestException("An error occurred")); + + // Act + var result = await _appwriteClient.Databases.UpdateDocument(request); + + // Assert + Assert.False(result.Success); + Assert.True(result.IsInternalError); + Assert.Equal("An error occurred", result.Result.AsT2.Message); + } +} diff --git a/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.UpdateDocument.cs b/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.UpdateDocument.cs new file mode 100644 index 00000000..7eaf2f65 --- /dev/null +++ b/tests/PinguApps.Appwrite.Server.Tests/Clients/Databases/DatabasesClientTests.UpdateDocument.cs @@ -0,0 +1,78 @@ +using System.Net; +using PinguApps.Appwrite.Shared.Requests.Databases; +using PinguApps.Appwrite.Shared.Tests; +using PinguApps.Appwrite.Shared.Utils; +using RichardSzalay.MockHttp; + +namespace PinguApps.Appwrite.Server.Tests.Clients.Databases; +public partial class DatabasesClientTests +{ + [Fact] + public async Task UpdateDocument_ShouldReturnSuccess_WhenApiCallSucceeds() + { + // Arrange + var request = UpdateDocumentRequest.CreateBuilder() + .WithDatabaseId(IdUtils.GenerateUniqueId()) + .WithCollectionId(IdUtils.GenerateUniqueId()) + .WithDocumentId(IdUtils.GenerateUniqueId()) + .AddField("test", "test") + .Build(); + + _mockHttp.Expect(HttpMethod.Patch, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/documents/{request.DocumentId}") + .ExpectedHeaders() + .Respond(TestConstants.AppJson, TestConstants.DocumentResponse); + + // Act + var result = await _appwriteClient.Databases.UpdateDocument(request); + + // Assert + Assert.True(result.Success); + } + + [Fact] + public async Task UpdateDocument_ShouldHandleException_WhenApiCallFails() + { + // Arrange + var request = UpdateDocumentRequest.CreateBuilder() + .WithDatabaseId(IdUtils.GenerateUniqueId()) + .WithCollectionId(IdUtils.GenerateUniqueId()) + .WithDocumentId(IdUtils.GenerateUniqueId()) + .AddField("test", "test") + .Build(); + + _mockHttp.Expect(HttpMethod.Patch, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/documents/{request.DocumentId}") + .ExpectedHeaders() + .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); + + // Act + var result = await _appwriteClient.Databases.UpdateDocument(request); + + // Assert + Assert.True(result.IsError); + Assert.True(result.IsAppwriteError); + } + + [Fact] + public async Task UpdateDocument_ShouldReturnErrorResponse_WhenExceptionOccurs() + { + // Arrange + var request = UpdateDocumentRequest.CreateBuilder() + .WithDatabaseId(IdUtils.GenerateUniqueId()) + .WithCollectionId(IdUtils.GenerateUniqueId()) + .WithDocumentId(IdUtils.GenerateUniqueId()) + .AddField("test", "test") + .Build(); + + _mockHttp.Expect(HttpMethod.Patch, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/documents/{request.DocumentId}") + .ExpectedHeaders() + .Throw(new HttpRequestException("An error occurred")); + + // Act + var result = await _appwriteClient.Databases.UpdateDocument(request); + + // Assert + Assert.False(result.Success); + Assert.True(result.IsInternalError); + Assert.Equal("An error occurred", result.Result.AsT2.Message); + } +} From c3202a74ad8e294467e75171043eeb8450bc3a4b Mon Sep 17 00:00:00 2001 From: Matthew Parker Date: Tue, 10 Dec 2024 22:05:56 +0000 Subject: [PATCH 21/22] Added tests to each documents client method, to check that when needed, session is added --- .../DatabasesClientTests.CreateDocument.cs | 24 +++++++++++++++++++ .../DatabasesClientTests.DeleteDocument.cs | 24 +++++++++++++++++++ .../DatabasesClientTests.GetDocument.cs | 24 +++++++++++++++++++ .../DatabasesClientTests.ListDocuments.cs | 23 ++++++++++++++++++ .../DatabasesClientTests.UpdateDocument.cs | 24 +++++++++++++++++++ 5 files changed, 119 insertions(+) diff --git a/tests/PinguApps.Appwrite.Client.Tests/Clients/Databases/DatabasesClientTests.CreateDocument.cs b/tests/PinguApps.Appwrite.Client.Tests/Clients/Databases/DatabasesClientTests.CreateDocument.cs index 7fda4022..1f44e84f 100644 --- a/tests/PinguApps.Appwrite.Client.Tests/Clients/Databases/DatabasesClientTests.CreateDocument.cs +++ b/tests/PinguApps.Appwrite.Client.Tests/Clients/Databases/DatabasesClientTests.CreateDocument.cs @@ -29,6 +29,30 @@ public async Task CreateDocument_ShouldReturnSuccess_WhenApiCallSucceeds() Assert.True(result.Success); } + [Fact] + public async Task CreateDocument_ShouldIncludeSessionHeaders_WhenProvided() + { + // Arrange + var request = CreateDocumentRequest.CreateBuilder() + .WithDatabaseId(IdUtils.GenerateUniqueId()) + .WithCollectionId(IdUtils.GenerateUniqueId()) + .AddField("AttributeName", "MyValue") + .Build(); + + _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/documents") + .ExpectedHeaders() + .WithJsonContent(request, _jsonSerializerOptions) + .Respond(TestConstants.AppJson, TestConstants.DocumentResponse); + + _appwriteClient.SetSession(TestConstants.Session); + + // Act + var result = await _appwriteClient.Databases.CreateDocument(request); + + // Assert + _mockHttp.VerifyNoOutstandingExpectation(); + } + [Fact] public async Task CreateDocument_ShouldHandleException_WhenApiCallFails() { diff --git a/tests/PinguApps.Appwrite.Client.Tests/Clients/Databases/DatabasesClientTests.DeleteDocument.cs b/tests/PinguApps.Appwrite.Client.Tests/Clients/Databases/DatabasesClientTests.DeleteDocument.cs index e713626b..ec2df9df 100644 --- a/tests/PinguApps.Appwrite.Client.Tests/Clients/Databases/DatabasesClientTests.DeleteDocument.cs +++ b/tests/PinguApps.Appwrite.Client.Tests/Clients/Databases/DatabasesClientTests.DeleteDocument.cs @@ -29,6 +29,30 @@ public async Task DeleteDocument_ShouldReturnSuccess_WhenApiCallSucceeds() Assert.True(result.Success); } + [Fact] + public async Task DeleteDocument_ShouldIncludeSessionHeaders_WhenProvided() + { + // Arrange + var request = new DeleteDocumentRequest + { + DatabaseId = IdUtils.GenerateUniqueId(), + CollectionId = IdUtils.GenerateUniqueId(), + DocumentId = IdUtils.GenerateUniqueId() + }; + + _mockHttp.Expect(HttpMethod.Delete, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/documents/{request.DocumentId}") + .ExpectedHeaders() + .Respond(HttpStatusCode.NoContent); + + _appwriteClient.SetSession(TestConstants.Session); + + // Act + var result = await _appwriteClient.Databases.DeleteDocument(request); + + // Assert + _mockHttp.VerifyNoOutstandingExpectation(); + } + [Fact] public async Task DeleteDocument_ShouldHandleException_WhenApiCallFails() { diff --git a/tests/PinguApps.Appwrite.Client.Tests/Clients/Databases/DatabasesClientTests.GetDocument.cs b/tests/PinguApps.Appwrite.Client.Tests/Clients/Databases/DatabasesClientTests.GetDocument.cs index 131e41eb..29af6f14 100644 --- a/tests/PinguApps.Appwrite.Client.Tests/Clients/Databases/DatabasesClientTests.GetDocument.cs +++ b/tests/PinguApps.Appwrite.Client.Tests/Clients/Databases/DatabasesClientTests.GetDocument.cs @@ -29,6 +29,30 @@ public async Task GetDocument_ShouldReturnSuccess_WhenApiCallSucceeds() Assert.True(result.Success); } + [Fact] + public async Task GetDocument_ShouldIncludeSessionHeaders_WhenProvided() + { + // Arrange + var request = new GetDocumentRequest + { + DatabaseId = IdUtils.GenerateUniqueId(), + CollectionId = IdUtils.GenerateUniqueId(), + DocumentId = IdUtils.GenerateUniqueId(), + }; + + _mockHttp.Expect(HttpMethod.Get, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/documents/{request.DocumentId}") + .ExpectedHeaders() + .Respond(TestConstants.AppJson, TestConstants.DocumentResponse); + + _appwriteClient.SetSession(TestConstants.Session); + + // Act + var result = await _appwriteClient.Databases.GetDocument(request); + + // Assert + _mockHttp.VerifyNoOutstandingExpectation(); + } + [Fact] public async Task GetDocument_ShouldProvideQueryParams_WhenQueriesProvided() { diff --git a/tests/PinguApps.Appwrite.Client.Tests/Clients/Databases/DatabasesClientTests.ListDocuments.cs b/tests/PinguApps.Appwrite.Client.Tests/Clients/Databases/DatabasesClientTests.ListDocuments.cs index 9b7aab76..1107abe5 100644 --- a/tests/PinguApps.Appwrite.Client.Tests/Clients/Databases/DatabasesClientTests.ListDocuments.cs +++ b/tests/PinguApps.Appwrite.Client.Tests/Clients/Databases/DatabasesClientTests.ListDocuments.cs @@ -28,6 +28,29 @@ public async Task ListDocuments_ShouldReturnSuccess_WhenApiCallSucceeds() Assert.True(result.Success); } + [Fact] + public async Task ListDocuments_ShouldIncludeSessionHeaders_WhenProvided() + { + // Arrange + var request = new ListDocumentsRequest + { + DatabaseId = IdUtils.GenerateUniqueId(), + CollectionId = IdUtils.GenerateUniqueId() + }; + + _mockHttp.Expect(HttpMethod.Get, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/documents") + .ExpectedHeaders(true) + .Respond(TestConstants.AppJson, TestConstants.DocumentsListResponse); + + _appwriteClient.SetSession(TestConstants.Session); + + // Act + var result = await _appwriteClient.Databases.ListDocuments(request); + + // Assert + _mockHttp.VerifyNoOutstandingExpectation(); + } + [Fact] public async Task ListDocuments_ShouldProvideQueryParams_WhenQueriesProvided() { diff --git a/tests/PinguApps.Appwrite.Client.Tests/Clients/Databases/DatabasesClientTests.UpdateDocument.cs b/tests/PinguApps.Appwrite.Client.Tests/Clients/Databases/DatabasesClientTests.UpdateDocument.cs index 7cd92fac..05e95f9a 100644 --- a/tests/PinguApps.Appwrite.Client.Tests/Clients/Databases/DatabasesClientTests.UpdateDocument.cs +++ b/tests/PinguApps.Appwrite.Client.Tests/Clients/Databases/DatabasesClientTests.UpdateDocument.cs @@ -29,6 +29,30 @@ public async Task UpdateDocument_ShouldReturnSuccess_WhenApiCallSucceeds() Assert.True(result.Success); } + [Fact] + public async Task UpdateDocument_ShouldIncludeSessionHeaders_WhenProvided() + { + // Arrange + var request = UpdateDocumentRequest.CreateBuilder() + .WithDatabaseId(IdUtils.GenerateUniqueId()) + .WithCollectionId(IdUtils.GenerateUniqueId()) + .WithDocumentId(IdUtils.GenerateUniqueId()) + .AddField("test", "test") + .Build(); + + _mockHttp.Expect(HttpMethod.Patch, $"{TestConstants.Endpoint}/databases/{request.DatabaseId}/collections/{request.CollectionId}/documents/{request.DocumentId}") + .ExpectedHeaders(true) + .Respond(TestConstants.AppJson, TestConstants.DocumentResponse); + + _appwriteClient.SetSession(TestConstants.Session); + + // Act + var result = await _appwriteClient.Databases.UpdateDocument(request); + + // Assert + _mockHttp.VerifyNoOutstandingExpectation(); + } + [Fact] public async Task UpdateDocument_ShouldHandleException_WhenApiCallFails() { From 7cb674eb3e11be23c8d87c73b86dae29d7569ddc Mon Sep 17 00:00:00 2001 From: Matthew Parker Date: Tue, 10 Dec 2024 22:16:19 +0000 Subject: [PATCH 22/22] Update README.md --- README.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 13cb326a..8700f46a 100644 --- a/README.md +++ b/README.md @@ -141,11 +141,11 @@ string emailAddressOrErrorMessage = userResponse.Result.Match( ## ⌛ Progress -![Server & Client - 162 / 317](https://img.shields.io/badge/Server_&_Client-162%20%2F%20317-gold?style=for-the-badge) +![Server & Client - 172 / 317](https://img.shields.io/badge/Server_&_Client-172%20%2F%20317-gold?style=for-the-badge) -![Server - 102 / 224](https://img.shields.io/badge/Server-102%20%2F%20224-gold?style=for-the-badge) +![Server - 107 / 224](https://img.shields.io/badge/Server-107%20%2F%20224-gold?style=for-the-badge) -![Client - 60 / 93](https://img.shields.io/badge/Client-60%20%2F%2093-gold?style=for-the-badge) +![Client - 65 / 93](https://img.shields.io/badge/Client-65%20%2F%2093-forestgreen?style=for-the-badge) ### 🔑 Key | Icon | Definition | @@ -275,7 +275,7 @@ string emailAddressOrErrorMessage = userResponse.Result.Match( | [Update Preferences](https://appwrite.io/docs/references/1.6.x/client-rest/teams#updatePrefs) | ✅ | ✅ | ### Databases -![Databases - 37 / 47](https://img.shields.io/badge/Databases-37%20%2F%2047-forestgreen?style=for-the-badge) +![Databases - 47 / 47](https://img.shields.io/badge/Databases-47%20%2F%2047-blue?style=for-the-badge) | Endpoint | Client | Server | |:-:|:-:|:-:| @@ -312,11 +312,11 @@ string emailAddressOrErrorMessage = userResponse.Result.Match( | [Get Attribute](https://appwrite.io/docs/references/1.6.x/server-rest/databases#getAttribute) | ❌ | ✅ | | [Delete Attribute](https://appwrite.io/docs/references/1.6.x/server-rest/databases#deleteAttribute) | ❌ | ✅ | | [Update Relationship Attribute](https://appwrite.io/docs/references/1.6.x/server-rest/databases#updateRelationshipAttribute) | ❌ | ✅ | -| [List Documents](https://appwrite.io/docs/references/1.6.x/client-rest/databases#listDocuments) | ⬛ | ⬛ | -| [Create Document](https://appwrite.io/docs/references/1.6.x/client-rest/databases#createDocument) | ⬛ | ⬛ | -| [Get Document](https://appwrite.io/docs/references/1.6.x/client-rest/databases#getDocument) | ⬛ | ⬛ | -| [Update Document](https://appwrite.io/docs/references/1.6.x/client-rest/databases#updateDocument) | ⬛ | ⬛ | -| [Delete Document](https://appwrite.io/docs/references/1.6.x/client-rest/databases#deleteDocument) | ⬛ | ⬛ | +| [List Documents](https://appwrite.io/docs/references/1.6.x/client-rest/databases#listDocuments) | ✅ | ✅ | +| [Create Document](https://appwrite.io/docs/references/1.6.x/client-rest/databases#createDocument) | ✅ | ✅ | +| [Get Document](https://appwrite.io/docs/references/1.6.x/client-rest/databases#getDocument) | ✅ | ✅ | +| [Update Document](https://appwrite.io/docs/references/1.6.x/client-rest/databases#updateDocument) | ✅ | ✅ | +| [Delete Document](https://appwrite.io/docs/references/1.6.x/client-rest/databases#deleteDocument) | ✅ | ✅ | | [List Indexes](https://appwrite.io/docs/references/1.6.x/server-rest/databases#listIndexes) | ❌ | ✅ | | [Create Index](https://appwrite.io/docs/references/1.6.x/server-rest/databases#createIndex) | ❌ | ✅ | | [Get Index](https://appwrite.io/docs/references/1.6.x/server-rest/databases#getIndex) | ❌ | ✅ |