From 3cd3bc1f6022b981337bf76f49c46c00275a4bd7 Mon Sep 17 00:00:00 2001 From: nullforce Date: Sun, 14 Aug 2022 18:51:11 -0500 Subject: [PATCH 1/5] Add Twibooru support for search, image, and featured image --- src/UrlBuilder/IGetFeaturedImage.cs | 6 ++ src/UrlBuilder/IGetImage.cs | 12 ++++ src/UrlBuilder/ISearch.cs | 53 +++++++++++++++ src/UrlBuilder/Twibooru/TwibooruBase.cs | 15 +++++ src/UrlBuilder/Twibooru/TwibooruClient.cs | 39 +++++++++++ .../Twibooru/TwibooruGetFeaturedImage.cs | 12 ++++ src/UrlBuilder/Twibooru/TwibooruGetImage.cs | 22 +++++++ src/UrlBuilder/Twibooru/TwibooruSearch.cs | 65 +++++++++++++++++++ .../TestConstants.cs | 1 + .../UrlBuilder/ISearchTests.cs | 38 +++++++++++ .../Twibooru/TwibooruGetFeaturedImageTests.cs | 16 +++++ .../Twibooru/TwibooruGetImageTests.cs | 27 ++++++++ .../Twibooru/TwibooruSearchTests.cs | 58 +++++++++++++++++ .../Nullforce.Api.Derpibooru.Tests/Usings.cs | 2 + 14 files changed, 366 insertions(+) create mode 100644 src/UrlBuilder/IGetFeaturedImage.cs create mode 100644 src/UrlBuilder/IGetImage.cs create mode 100644 src/UrlBuilder/ISearch.cs create mode 100644 src/UrlBuilder/Twibooru/TwibooruBase.cs create mode 100644 src/UrlBuilder/Twibooru/TwibooruClient.cs create mode 100644 src/UrlBuilder/Twibooru/TwibooruGetFeaturedImage.cs create mode 100644 src/UrlBuilder/Twibooru/TwibooruGetImage.cs create mode 100644 src/UrlBuilder/Twibooru/TwibooruSearch.cs create mode 100644 tests/Nullforce.Api.Derpibooru.Tests/UrlBuilder/ISearchTests.cs create mode 100644 tests/Nullforce.Api.Derpibooru.Tests/UrlBuilder/Twibooru/TwibooruGetFeaturedImageTests.cs create mode 100644 tests/Nullforce.Api.Derpibooru.Tests/UrlBuilder/Twibooru/TwibooruGetImageTests.cs create mode 100644 tests/Nullforce.Api.Derpibooru.Tests/UrlBuilder/Twibooru/TwibooruSearchTests.cs diff --git a/src/UrlBuilder/IGetFeaturedImage.cs b/src/UrlBuilder/IGetFeaturedImage.cs new file mode 100644 index 0000000..7f82fd0 --- /dev/null +++ b/src/UrlBuilder/IGetFeaturedImage.cs @@ -0,0 +1,6 @@ +namespace Nullforce.Api.UrlBuilder; + +public interface IGetFeaturedImage +{ + public string Uri { get; } +} diff --git a/src/UrlBuilder/IGetImage.cs b/src/UrlBuilder/IGetImage.cs new file mode 100644 index 0000000..887b618 --- /dev/null +++ b/src/UrlBuilder/IGetImage.cs @@ -0,0 +1,12 @@ +namespace Nullforce.Api.UrlBuilder; + +public interface IGetImage +{ + public string Uri { get; } + + /// + /// Applies a Derpibooru filter + /// + /// A user or system filter ID (See https://www.derpibooru.org/filters) + public IGetImage WithFilterId(int filterId); +} diff --git a/src/UrlBuilder/ISearch.cs b/src/UrlBuilder/ISearch.cs new file mode 100644 index 0000000..4faa747 --- /dev/null +++ b/src/UrlBuilder/ISearch.cs @@ -0,0 +1,53 @@ +namespace Nullforce.Api.UrlBuilder; + +public interface ISearch +{ + public string Uri { get; } + + /// + /// Specifies a search query filter + /// + /// + /// Search my favorites: my:faves, !my:faves + /// Search my upvotes: my:upvotes, !my:upvotes + /// Search my downvotes: my:downvotes, !my:downvotes + /// Search my uploads: my:uploads, !my:uploads + /// Search my watched: my:watched, !my:watched + /// + /// A query string following the syntax at https://derpibooru.org/pages/search_syntax + public ISearch WithQuery(string query); + + /// + /// Applies a Derpibooru filter + /// + /// A user or system filter ID (See https://www.derpibooru.org/filters) + public ISearch WithFilterId(int filterId); + + /// + /// Applies a Derpibooru sort option + /// + /// A sort option + public ISearch SortBy(string sort); + + /// + /// Sorts the results in ascending order + /// + public ISearch SortAscending(); + + /// + /// Sorts the results in descending order + /// + public ISearch SortDescending(); + + /// + /// The page number for the search results + /// + /// A 1-indexed page number + public ISearch Page(int page); + + /// + /// The number of search results to return per page + /// + /// A limit between 1 and 50 + public ISearch PerPage(int limit); +} diff --git a/src/UrlBuilder/Twibooru/TwibooruBase.cs b/src/UrlBuilder/Twibooru/TwibooruBase.cs new file mode 100644 index 0000000..a6bcbba --- /dev/null +++ b/src/UrlBuilder/Twibooru/TwibooruBase.cs @@ -0,0 +1,15 @@ +namespace Nullforce.Api.UrlBuilder.Twibooru; + +public abstract class TwibooruBase +{ + protected readonly string _apiBaseUri; + protected readonly string _apiKey; + protected string _uri; + public string Uri => _uri; + + public TwibooruBase(string apiBaseUri, string apiKey) + { + _apiBaseUri = apiBaseUri; + _apiKey = apiKey; + } +} diff --git a/src/UrlBuilder/Twibooru/TwibooruClient.cs b/src/UrlBuilder/Twibooru/TwibooruClient.cs new file mode 100644 index 0000000..f94cb48 --- /dev/null +++ b/src/UrlBuilder/Twibooru/TwibooruClient.cs @@ -0,0 +1,39 @@ +namespace Nullforce.Api.UrlBuilder.Twibooru; + +public class TwibooruClient +{ + private readonly string _apiBaseUri = "https://twibooru.org/api/v3"; + private readonly string _apiKey; + + public TwibooruClient() + { + } + + public TwibooruClient(string apiKey) + { + _apiKey = apiKey; + } + + public TwibooruGetImage GetImage(int imageId) + { + return new TwibooruGetImage(_apiBaseUri, _apiKey, imageId); + } + + /// + /// Gets the image response for the featured image + /// + /// A fluent API wrapper for featured image + public TwibooruGetFeaturedImage GetFeaturedImage() + { + return new TwibooruGetFeaturedImage(_apiBaseUri, _apiKey); + } + + /// + /// Exposes the Twibooru Search as a Fluent API. + /// + /// A fluent API wrapper for search + public TwibooruSearch Search() + { + return new TwibooruSearch(_apiBaseUri, _apiKey); + } +} diff --git a/src/UrlBuilder/Twibooru/TwibooruGetFeaturedImage.cs b/src/UrlBuilder/Twibooru/TwibooruGetFeaturedImage.cs new file mode 100644 index 0000000..a1a65ad --- /dev/null +++ b/src/UrlBuilder/Twibooru/TwibooruGetFeaturedImage.cs @@ -0,0 +1,12 @@ +using Flurl; + +namespace Nullforce.Api.UrlBuilder.Twibooru; + +public class TwibooruGetFeaturedImage : TwibooruBase, IGetFeaturedImage +{ + public TwibooruGetFeaturedImage(string apiBaseUri, string apiKey) + : base(apiBaseUri, apiKey) + { + _uri = apiBaseUri.AppendPathSegment("posts/featured"); + } +} diff --git a/src/UrlBuilder/Twibooru/TwibooruGetImage.cs b/src/UrlBuilder/Twibooru/TwibooruGetImage.cs new file mode 100644 index 0000000..59a75d8 --- /dev/null +++ b/src/UrlBuilder/Twibooru/TwibooruGetImage.cs @@ -0,0 +1,22 @@ +using Flurl; + +namespace Nullforce.Api.UrlBuilder.Twibooru; + +public class TwibooruGetImage : TwibooruBase, IGetImage +{ + public TwibooruGetImage(string apiBaseUri, string apiKey, int imageId) + : base(apiBaseUri, apiKey) + { + _uri = apiBaseUri.AppendPathSegment($"images/{imageId}"); + } + + /// + /// Applies a Twibooru filter + /// + /// A user or system filter ID + public IGetImage WithFilterId(int filterId) + { + _uri = _uri.SetQueryParam("filter_id", filterId); + return this; + } +} diff --git a/src/UrlBuilder/Twibooru/TwibooruSearch.cs b/src/UrlBuilder/Twibooru/TwibooruSearch.cs new file mode 100644 index 0000000..74289a7 --- /dev/null +++ b/src/UrlBuilder/Twibooru/TwibooruSearch.cs @@ -0,0 +1,65 @@ +using Flurl; + +namespace Nullforce.Api.UrlBuilder.Twibooru; + +public class TwibooruSearch : TwibooruBase, ISearch +{ + public TwibooruSearch(string apiBaseUri, string apiKey) + : base(apiBaseUri, apiKey) + { + _uri = apiBaseUri.AppendPathSegment("search/posts"); + + // Setup defaults + _uri = _uri + .SetQueryParam("q", "*") + .SetQueryParam("sf", "created_at") + .SetQueryParam("sd", "desc"); + + if (!string.IsNullOrWhiteSpace(apiKey)) + { + _uri = _uri.SetQueryParam("key", apiKey); + } + } + + public ISearch Page(int page) + { + _uri = _uri.SetQueryParam("page", page); + return this; + } + + public ISearch PerPage(int limit) + { + _uri = _uri.SetQueryParam("perpage", limit); + return this; + } + + public ISearch SortAscending() + { + _uri = _uri.SetQueryParam("sd", "asc"); + return this; + } + + public ISearch SortBy(string sort) + { + _uri = _uri.SetQueryParam("sf", sort); + return this; + } + + public ISearch SortDescending() + { + _uri = _uri.SetQueryParam("sd", "desc"); + return this; + } + + public ISearch WithFilterId(int filterId) + { + _uri = _uri.SetQueryParam("filter_id", filterId); + return this; + } + + public ISearch WithQuery(string query) + { + _uri = _uri.SetQueryParam("q", query); + return this; + } +} diff --git a/tests/Nullforce.Api.Derpibooru.Tests/TestConstants.cs b/tests/Nullforce.Api.Derpibooru.Tests/TestConstants.cs index 13251c8..805eac0 100644 --- a/tests/Nullforce.Api.Derpibooru.Tests/TestConstants.cs +++ b/tests/Nullforce.Api.Derpibooru.Tests/TestConstants.cs @@ -4,4 +4,5 @@ public static class TestConstants { public const string Category = "Category"; public const string DerpibooruCall = "DerpibooruCall"; + public const string TwibooruCall = "TwibooruCall"; } diff --git a/tests/Nullforce.Api.Derpibooru.Tests/UrlBuilder/ISearchTests.cs b/tests/Nullforce.Api.Derpibooru.Tests/UrlBuilder/ISearchTests.cs new file mode 100644 index 0000000..f0d69b7 --- /dev/null +++ b/tests/Nullforce.Api.Derpibooru.Tests/UrlBuilder/ISearchTests.cs @@ -0,0 +1,38 @@ +using Nullforce.Api.UrlBuilder; +using Nullforce.Api.UrlBuilder.Derpibooru; +using Nullforce.Api.UrlBuilder.Twibooru; + +namespace Nullforce.Api.Derpibooru.Tests.UrlBuilder; + +public class ISearchTests +{ + private readonly DerpiClient _derpibooruClient = new(); + private readonly TwibooruClient _twibooruClient = new(); + + [Fact] + public void Search_IsInterchangeable() + { + var derpibooru = _derpibooruClient.Search(); + var twibooru = _twibooruClient.Search(); + + var derpibooruSearchUri = UseSearch(derpibooru); + var twibooruSearchUri = UseSearch(twibooru); + + using var _ = new AssertionScope(); + + derpibooruSearchUri.Should().NotBeEmpty(); + twibooruSearchUri.Should().NotBeEmpty(); + } + + private string UseSearch(ISearch search) + { + return search + .WithQuery("test") + .WithFilterId(1) + .SortBy("created_at") + .SortAscending() + .Page(1) + .PerPage(50) + .Uri; + } +} diff --git a/tests/Nullforce.Api.Derpibooru.Tests/UrlBuilder/Twibooru/TwibooruGetFeaturedImageTests.cs b/tests/Nullforce.Api.Derpibooru.Tests/UrlBuilder/Twibooru/TwibooruGetFeaturedImageTests.cs new file mode 100644 index 0000000..0f53570 --- /dev/null +++ b/tests/Nullforce.Api.Derpibooru.Tests/UrlBuilder/Twibooru/TwibooruGetFeaturedImageTests.cs @@ -0,0 +1,16 @@ +using Nullforce.Api.UrlBuilder.Twibooru; + +namespace Nullforce.Api.Derpibooru.Tests.UrlBuilder.Twibooru; + +public class TwibooruGetFeaturedImageTests +{ + private readonly TwibooruClient _client = new(); + + [Fact] + public void GetFeaturedImage_BuildsUrl() + { + var uri = _client.GetFeaturedImage().Uri; + + uri.Should().Be("https://twibooru.org/api/v3/posts/featured"); + } +} diff --git a/tests/Nullforce.Api.Derpibooru.Tests/UrlBuilder/Twibooru/TwibooruGetImageTests.cs b/tests/Nullforce.Api.Derpibooru.Tests/UrlBuilder/Twibooru/TwibooruGetImageTests.cs new file mode 100644 index 0000000..ddaad46 --- /dev/null +++ b/tests/Nullforce.Api.Derpibooru.Tests/UrlBuilder/Twibooru/TwibooruGetImageTests.cs @@ -0,0 +1,27 @@ +using Nullforce.Api.UrlBuilder.Twibooru; + +namespace Nullforce.Api.Derpibooru.Tests.UrlBuilder.Twibooru; + +public class TwibooruGetImageTests +{ + private readonly TwibooruClient _client = new(); + + [Fact] + public void GetImage_BuildsUrl() + { + var uri = _client.GetImage(1).Uri; + + uri.Should().Be("https://twibooru.org/api/v3/images/1"); + } + + [Fact] + public void GetImage_WithFilterId_BuildsUrl() + { + var uri = _client + .GetImage(1) + .WithFilterId(2) + .Uri; + + uri.Should().Contain("filter_id=2"); + } +} diff --git a/tests/Nullforce.Api.Derpibooru.Tests/UrlBuilder/Twibooru/TwibooruSearchTests.cs b/tests/Nullforce.Api.Derpibooru.Tests/UrlBuilder/Twibooru/TwibooruSearchTests.cs new file mode 100644 index 0000000..f4fda8d --- /dev/null +++ b/tests/Nullforce.Api.Derpibooru.Tests/UrlBuilder/Twibooru/TwibooruSearchTests.cs @@ -0,0 +1,58 @@ +using Nullforce.Api.JsonModels.Twibooru; +using Nullforce.Api.UrlBuilder.Twibooru; + +namespace Nullforce.Api.Derpibooru.Tests.UrlBuilder.Twibooru; + +public class TwibooruSearchTests +{ + private readonly TwibooruSearch _search = new("https://twibooru.org/api/v3", string.Empty); + + public TwibooruSearchTests() + { + // Do this in Startup. All calls to the URI will use the same HttpClient instance. + FlurlHttp.ConfigureClient("https://derpibooru.org/api/v1/json", cli => cli + .WithHeaders(new + { + Accept = "application/json", + User_Agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.75 Safari/537.36" + })); + } + + [Fact] + public async Task Search_WithDefaults_ReturnsResults() + { + var uri = _search.Uri; + var json = await uri.GetStringAsync(); + var searchResult = JsonSerializer.Deserialize(json); + + uri.Should().Be("https://twibooru.org/api/v3/search/posts?q=%2A&sf=created_at&sd=desc"); + + searchResult.Should().NotBeNull(); + searchResult.JsonExtensionData.Should().BeNull(); + searchResult.Posts.Should().NotBeNull(); + searchResult.Total.Should().BeGreaterThanOrEqualTo(1); + } + + [Fact] + public async Task Search_WithId_ReturnsResults() + { + var uri = _search + .WithQuery("id:3") + .Uri; + var json = await uri.GetStringAsync(); + var searchResult = JsonSerializer.Deserialize(json); + + using var _ = new AssertionScope(); + + searchResult.Should().NotBeNull(); + searchResult.JsonExtensionData.Should().BeNull(); + + searchResult.Posts.Should().NotBeNull(); + searchResult.Posts.Should().HaveCount(1); + searchResult.Posts[0].MediaType.Should().Be("image"); + + searchResult.Total.Should().Be(1); + } + + +} diff --git a/tests/Nullforce.Api.Derpibooru.Tests/Usings.cs b/tests/Nullforce.Api.Derpibooru.Tests/Usings.cs index 55792a8..6d83bed 100644 --- a/tests/Nullforce.Api.Derpibooru.Tests/Usings.cs +++ b/tests/Nullforce.Api.Derpibooru.Tests/Usings.cs @@ -1,5 +1,7 @@ global using FluentAssertions; +global using FluentAssertions.Execution; global using Flurl; global using Flurl.Http; +global using System.Text.Json; global using System.Threading.Tasks; global using Xunit; From 149864b0db7e1d36368025c76a859121392f9b03 Mon Sep 17 00:00:00 2001 From: nullforce Date: Sun, 14 Aug 2022 18:52:06 -0500 Subject: [PATCH 2/5] Refactor Derpibooru classes to use new interfaces --- src/{ => UrlBuilder/Derpibooru}/DerpiBase.cs | 4 ++-- .../Derpibooru}/DerpiClient.cs | 2 +- .../Derpibooru}/DerpiGetFeaturedImage.cs | 4 ++-- .../Derpibooru}/DerpiGetImage.cs | 8 +++---- .../Derpibooru}/DerpiSearch.cs | 22 +++++++++---------- .../Derpibooru}/DerpiSortOptions.cs | 2 +- .../Derpibooru}/DerpiSystemFilter.cs | 2 +- .../DerpibooruGetFeaturedImageTests.cs | 18 +++++++++++++++ .../Derpibooru/DerpibooruGetImageTests.cs} | 9 ++++---- .../Derpibooru/DerpibooruSearchTests.cs | 5 +++++ .../Derpibooru}/SearchTests.cs | 5 +++-- 11 files changed, 53 insertions(+), 28 deletions(-) rename src/{ => UrlBuilder/Derpibooru}/DerpiBase.cs (76%) rename src/{ => UrlBuilder/Derpibooru}/DerpiClient.cs (95%) rename src/{ => UrlBuilder/Derpibooru}/DerpiGetFeaturedImage.cs (63%) rename src/{ => UrlBuilder/Derpibooru}/DerpiGetImage.cs (69%) rename src/{ => UrlBuilder/Derpibooru}/DerpiSearch.cs (89%) rename src/{ => UrlBuilder/Derpibooru}/DerpiSortOptions.cs (90%) rename src/{ => UrlBuilder/Derpibooru}/DerpiSystemFilter.cs (95%) create mode 100644 tests/Nullforce.Api.Derpibooru.Tests/UrlBuilder/Derpibooru/DerpibooruGetFeaturedImageTests.cs rename tests/Nullforce.Api.Derpibooru.Tests/{ImageTests.cs => UrlBuilder/Derpibooru/DerpibooruGetImageTests.cs} (85%) create mode 100644 tests/Nullforce.Api.Derpibooru.Tests/UrlBuilder/Derpibooru/DerpibooruSearchTests.cs rename tests/Nullforce.Api.Derpibooru.Tests/{ => UrlBuilder/Derpibooru}/SearchTests.cs (95%) diff --git a/src/DerpiBase.cs b/src/UrlBuilder/Derpibooru/DerpiBase.cs similarity index 76% rename from src/DerpiBase.cs rename to src/UrlBuilder/Derpibooru/DerpiBase.cs index 144eec9..c608718 100644 --- a/src/DerpiBase.cs +++ b/src/UrlBuilder/Derpibooru/DerpiBase.cs @@ -1,6 +1,6 @@ -namespace Nullforce.Api.Derpibooru; +namespace Nullforce.Api.UrlBuilder.Derpibooru; -public class DerpiBase +public abstract class DerpiBase { protected readonly string _apiBaseUri; protected readonly string _apiKey; diff --git a/src/DerpiClient.cs b/src/UrlBuilder/Derpibooru/DerpiClient.cs similarity index 95% rename from src/DerpiClient.cs rename to src/UrlBuilder/Derpibooru/DerpiClient.cs index 3fc859e..187d29d 100644 --- a/src/DerpiClient.cs +++ b/src/UrlBuilder/Derpibooru/DerpiClient.cs @@ -1,4 +1,4 @@ -namespace Nullforce.Api.Derpibooru; +namespace Nullforce.Api.UrlBuilder.Derpibooru; public class DerpiClient { diff --git a/src/DerpiGetFeaturedImage.cs b/src/UrlBuilder/Derpibooru/DerpiGetFeaturedImage.cs similarity index 63% rename from src/DerpiGetFeaturedImage.cs rename to src/UrlBuilder/Derpibooru/DerpiGetFeaturedImage.cs index e0ad9d7..cfc8781 100644 --- a/src/DerpiGetFeaturedImage.cs +++ b/src/UrlBuilder/Derpibooru/DerpiGetFeaturedImage.cs @@ -1,8 +1,8 @@ using Flurl; -namespace Nullforce.Api.Derpibooru; +namespace Nullforce.Api.UrlBuilder.Derpibooru; -public class DerpiGetFeaturedImage : DerpiBase +public class DerpiGetFeaturedImage : DerpiBase, IGetFeaturedImage { public DerpiGetFeaturedImage(string apiBaseUri, string apiKey) : base(apiBaseUri, apiKey) diff --git a/src/DerpiGetImage.cs b/src/UrlBuilder/Derpibooru/DerpiGetImage.cs similarity index 69% rename from src/DerpiGetImage.cs rename to src/UrlBuilder/Derpibooru/DerpiGetImage.cs index 645b4fa..33dc859 100644 --- a/src/DerpiGetImage.cs +++ b/src/UrlBuilder/Derpibooru/DerpiGetImage.cs @@ -1,8 +1,8 @@ using Flurl; -namespace Nullforce.Api.Derpibooru; +namespace Nullforce.Api.UrlBuilder.Derpibooru; -public class DerpiGetImage : DerpiBase +public class DerpiGetImage : DerpiBase, IGetImage { public DerpiGetImage(string apiBaseUri, string apiKey, int imageId) : base(apiBaseUri, apiKey) @@ -13,8 +13,8 @@ public DerpiGetImage(string apiBaseUri, string apiKey, int imageId) /// /// Applies a Derpibooru filter /// - /// A user or system filter ID (See https://www.derpibooru.org/filters) - public DerpiGetImage WithFilterId(int filterId) + /// A user or system filter ID (See https://www.derpibooru.org/filters) + public IGetImage WithFilterId(int filterId) { _uri = _uri.SetQueryParam("filter_id", filterId); return this; diff --git a/src/DerpiSearch.cs b/src/UrlBuilder/Derpibooru/DerpiSearch.cs similarity index 89% rename from src/DerpiSearch.cs rename to src/UrlBuilder/Derpibooru/DerpiSearch.cs index af240d8..3284ecb 100644 --- a/src/DerpiSearch.cs +++ b/src/UrlBuilder/Derpibooru/DerpiSearch.cs @@ -1,8 +1,8 @@ using Flurl; -namespace Nullforce.Api.Derpibooru; +namespace Nullforce.Api.UrlBuilder.Derpibooru; -public class DerpiSearch : DerpiBase +public class DerpiSearch : DerpiBase, ISearch { public DerpiSearch(string apiBaseUri, string apiKey) : base(apiBaseUri, apiKey) @@ -28,7 +28,7 @@ public DerpiSearch(string apiBaseUri, string apiKey) /// Search my watched: my:watched, !my:watched /// /// A query string following the syntax at https://derpibooru.org/pages/search_syntax - public DerpiSearch WithQuery(string query) + public ISearch WithQuery(string query) { // TODO: query validation _uri = _uri.SetQueryParam("q", query); @@ -39,7 +39,7 @@ public DerpiSearch WithQuery(string query) /// Applies a Derpibooru filter /// /// A user or system filter ID (See https://www.derpibooru.org/filters) - public DerpiSearch WithFilterId(int filterId) + public ISearch WithFilterId(int filterId) { _uri = _uri.SetQueryParam("filter_id", filterId); return this; @@ -51,14 +51,14 @@ public DerpiSearch WithFilterId(int filterId) /// A system filter (See https://www.derpibooru.org/filters) public DerpiSearch WithFilterId(DerpiSystemFilter filter) { - return WithFilterId((int)filter); + return WithFilterId((int)filter) as DerpiSearch; } /// /// Applies a Derpibooru sort option /// /// A sort option - public DerpiSearch SortBy(string sort) + public ISearch SortBy(string sort) { _uri = _uri.SetQueryParam("sf", sort); return this; @@ -107,13 +107,13 @@ public DerpiSearch SortBy(DerpiSortOptions sortOption) break; } - return SortBy(sort); + return SortBy(sort) as DerpiSearch; } /// /// Sorts the results in ascending order /// - public DerpiSearch SortAscending() + public ISearch SortAscending() { _uri = _uri.SetQueryParam("sd", "asc"); return this; @@ -122,7 +122,7 @@ public DerpiSearch SortAscending() /// /// Sorts the results in descending order /// - public DerpiSearch SortDescending() + public ISearch SortDescending() { _uri = _uri.SetQueryParam("sd", "desc"); return this; @@ -133,7 +133,7 @@ public DerpiSearch SortDescending() /// /// A 1-indexed page number /// - public DerpiSearch Page(int page) + public ISearch Page(int page) { _uri = _uri.SetQueryParam("page", page); return this; @@ -144,7 +144,7 @@ public DerpiSearch Page(int page) /// /// A limit between 1 and 50 /// - public DerpiSearch PerPage(int limit) + public ISearch PerPage(int limit) { _uri = _uri.SetQueryParam("perpage", limit); return this; diff --git a/src/DerpiSortOptions.cs b/src/UrlBuilder/Derpibooru/DerpiSortOptions.cs similarity index 90% rename from src/DerpiSortOptions.cs rename to src/UrlBuilder/Derpibooru/DerpiSortOptions.cs index e3b9a3d..f8a0997 100644 --- a/src/DerpiSortOptions.cs +++ b/src/UrlBuilder/Derpibooru/DerpiSortOptions.cs @@ -1,6 +1,6 @@ using System; -namespace Nullforce.Api.Derpibooru; +namespace Nullforce.Api.UrlBuilder.Derpibooru; public enum DerpiSortOptions { diff --git a/src/DerpiSystemFilter.cs b/src/UrlBuilder/Derpibooru/DerpiSystemFilter.cs similarity index 95% rename from src/DerpiSystemFilter.cs rename to src/UrlBuilder/Derpibooru/DerpiSystemFilter.cs index 2fd619a..2452d52 100644 --- a/src/DerpiSystemFilter.cs +++ b/src/UrlBuilder/Derpibooru/DerpiSystemFilter.cs @@ -1,4 +1,4 @@ -namespace Nullforce.Api.Derpibooru; +namespace Nullforce.Api.UrlBuilder.Derpibooru; public enum DerpiSystemFilter { diff --git a/tests/Nullforce.Api.Derpibooru.Tests/UrlBuilder/Derpibooru/DerpibooruGetFeaturedImageTests.cs b/tests/Nullforce.Api.Derpibooru.Tests/UrlBuilder/Derpibooru/DerpibooruGetFeaturedImageTests.cs new file mode 100644 index 0000000..1cc66ad --- /dev/null +++ b/tests/Nullforce.Api.Derpibooru.Tests/UrlBuilder/Derpibooru/DerpibooruGetFeaturedImageTests.cs @@ -0,0 +1,18 @@ +using Nullforce.Api.UrlBuilder.Derpibooru; + +namespace Nullforce.Api.Derpibooru.Tests.UrlBuilder.Derpibooru; + +public class DerpibooruGetFeaturedImageTests +{ + private readonly DerpiClient _client = new(); + + [Fact] + public void GetFeaturedImage_BuildsUrl() + { + var uri = _client + .GetFeaturedImage() + .Uri; + + uri.Should().Be("https://derpibooru.org/api/v1/json/images/featured"); + } +} diff --git a/tests/Nullforce.Api.Derpibooru.Tests/ImageTests.cs b/tests/Nullforce.Api.Derpibooru.Tests/UrlBuilder/Derpibooru/DerpibooruGetImageTests.cs similarity index 85% rename from tests/Nullforce.Api.Derpibooru.Tests/ImageTests.cs rename to tests/Nullforce.Api.Derpibooru.Tests/UrlBuilder/Derpibooru/DerpibooruGetImageTests.cs index e045ce2..b935da9 100644 --- a/tests/Nullforce.Api.Derpibooru.Tests/ImageTests.cs +++ b/tests/Nullforce.Api.Derpibooru.Tests/UrlBuilder/Derpibooru/DerpibooruGetImageTests.cs @@ -1,12 +1,13 @@ -using Nullforce.Api.Derpibooru.JsonModels; +using Nullforce.Api.JsonModels.Philomena; +using Nullforce.Api.UrlBuilder.Derpibooru; -namespace Nullforce.Api.Derpibooru.Tests; +namespace Nullforce.Api.Derpibooru.Tests.UrlBuilder.Derpibooru; -public class ImageTests +public class DerpibooruGetImageTests { private readonly DerpiClient _client = new (); - public ImageTests() + public DerpibooruGetImageTests() { // Do this in Startup. All calls to the URI will use the same HttpClient instance. FlurlHttp.ConfigureClient("https://derpibooru.org/api/v1/json", cli => cli diff --git a/tests/Nullforce.Api.Derpibooru.Tests/UrlBuilder/Derpibooru/DerpibooruSearchTests.cs b/tests/Nullforce.Api.Derpibooru.Tests/UrlBuilder/Derpibooru/DerpibooruSearchTests.cs new file mode 100644 index 0000000..53160ed --- /dev/null +++ b/tests/Nullforce.Api.Derpibooru.Tests/UrlBuilder/Derpibooru/DerpibooruSearchTests.cs @@ -0,0 +1,5 @@ +namespace Nullforce.Api.Derpibooru.Tests.UrlBuilder.Derpibooru; + +public class DerpibooruSearchTests +{ +} diff --git a/tests/Nullforce.Api.Derpibooru.Tests/SearchTests.cs b/tests/Nullforce.Api.Derpibooru.Tests/UrlBuilder/Derpibooru/SearchTests.cs similarity index 95% rename from tests/Nullforce.Api.Derpibooru.Tests/SearchTests.cs rename to tests/Nullforce.Api.Derpibooru.Tests/UrlBuilder/Derpibooru/SearchTests.cs index 5017e82..5df9423 100644 --- a/tests/Nullforce.Api.Derpibooru.Tests/SearchTests.cs +++ b/tests/Nullforce.Api.Derpibooru.Tests/UrlBuilder/Derpibooru/SearchTests.cs @@ -1,6 +1,7 @@ -using Nullforce.Api.Derpibooru.JsonModels; +using Nullforce.Api.JsonModels.Philomena; +using Nullforce.Api.UrlBuilder.Derpibooru; -namespace Nullforce.Api.Derpibooru.Tests; +namespace Nullforce.Api.Derpibooru.Tests.UrlBuilder.Derpibooru; public class SearchTests { From 05dccd421671d9c4f1bf5b389d8b200f0bd40639 Mon Sep 17 00:00:00 2001 From: nullforce Date: Sun, 14 Aug 2022 18:52:21 -0500 Subject: [PATCH 3/5] Update package info --- LICENSE.txt => LICENSE | 0 README.md | 16 ++++++++++------ src/Nullforce.Api.Derpibooru.csproj | 16 +++------------- 3 files changed, 13 insertions(+), 19 deletions(-) rename LICENSE.txt => LICENSE (100%) diff --git a/LICENSE.txt b/LICENSE similarity index 100% rename from LICENSE.txt rename to LICENSE diff --git a/README.md b/README.md index 3666a2b..c47f0ff 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,15 @@ # Nullforce.Api.Derpibooru -A .NET Standard library for consuming derpibooru.org API endpoints. +A .NET Standard library for consuming Philomena API endpoints. -||| -----------------------|--- -**Build** | [![Build Status](https://github.com/nullforce-public/Nullforce.Api.Derpibooru/workflows/build/badge.svg?branch=main)](https://github.com/nullforce-public/Nullforce.Api.Derpibooru/actions) -**NuGet** | [![nuget](https://img.shields.io/nuget/v/Nullforce.Api.Derpibooru.svg)](https://www.nuget.org/packages/Nullforce.Api.Derpibooru/) -**NuGet (prerelease)**| [![nuget](https://img.shields.io/nuget/vpre/Nullforce.Api.Derpibooru.svg)](https://www.nuget.org/packages/Nullforce.Api.Derpibooru/) +Also Supports: +- derpibooru.org +- twibooru.org + +| | | +|----------------------|---| +|**Build** | [![Build Status](https://github.com/nullforce-public/Nullforce.Api.Derpibooru/workflows/build/badge.svg?branch=main)](https://github.com/nullforce-public/Nullforce.Api.Derpibooru/actions)| +|**NuGet** | [![nuget](https://img.shields.io/nuget/v/Nullforce.Api.Derpibooru.svg)](https://www.nuget.org/packages/Nullforce.Api.Derpibooru/)| +|**NuGet (prerelease)**| [![nuget](https://img.shields.io/nuget/vpre/Nullforce.Api.Derpibooru.svg)](https://www.nuget.org/packages/Nullforce.Api.Derpibooru/)| ## Usage Example diff --git a/src/Nullforce.Api.Derpibooru.csproj b/src/Nullforce.Api.Derpibooru.csproj index 5f9a9f4..57f7878 100644 --- a/src/Nullforce.Api.Derpibooru.csproj +++ b/src/Nullforce.Api.Derpibooru.csproj @@ -3,16 +3,6 @@ netstandard2.0 latest - true - 0.1.0 - Nullforce - A C# wrapper for the Derpibooru API - Copyright 2019-2022 nullforce - https://github.com/nullforce-public/Nullforce.Api.Derpibooru - git - derpibooru - MIT - false @@ -24,7 +14,7 @@ https://github.com/nullforce-public/Nullforce.Api.Derpibooru git icon.png - derpibooru + derpibooru philomena twibooru MIT README.md false @@ -36,12 +26,12 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + - + From d7885a35b4b35e96c4eb664bbc3c15cc8adb8452 Mon Sep 17 00:00:00 2001 From: nullforce Date: Sun, 14 Aug 2022 19:03:15 -0500 Subject: [PATCH 4/5] Cleanup duplicate, empty test --- .../Derpibooru/DerpibooruSearchTests.cs | 104 ++++++++++++++++- .../UrlBuilder/Derpibooru/SearchTests.cs | 107 ------------------ 2 files changed, 103 insertions(+), 108 deletions(-) delete mode 100644 tests/Nullforce.Api.Derpibooru.Tests/UrlBuilder/Derpibooru/SearchTests.cs diff --git a/tests/Nullforce.Api.Derpibooru.Tests/UrlBuilder/Derpibooru/DerpibooruSearchTests.cs b/tests/Nullforce.Api.Derpibooru.Tests/UrlBuilder/Derpibooru/DerpibooruSearchTests.cs index 53160ed..99081d1 100644 --- a/tests/Nullforce.Api.Derpibooru.Tests/UrlBuilder/Derpibooru/DerpibooruSearchTests.cs +++ b/tests/Nullforce.Api.Derpibooru.Tests/UrlBuilder/Derpibooru/DerpibooruSearchTests.cs @@ -1,5 +1,107 @@ -namespace Nullforce.Api.Derpibooru.Tests.UrlBuilder.Derpibooru; +using Nullforce.Api.JsonModels.Philomena; +using Nullforce.Api.UrlBuilder.Derpibooru; + +namespace Nullforce.Api.Derpibooru.Tests.UrlBuilder.Derpibooru; public class DerpibooruSearchTests { + private readonly DerpiClient _client = new(); + + public DerpibooruSearchTests() + { + // Do this in Startup. All calls to the URI will use the same HttpClient instance. + FlurlHttp.ConfigureClient("https://derpibooru.org/api/v1/json", cli => cli + .WithHeaders(new + { + Accept = "application/json", + User_Agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.75 Safari/537.36" + })); + } + + [Fact] + [Trait(TestConstants.Category, TestConstants.DerpibooruCall)] + public async Task SearchRawUri() + { + var uri = "https://derpibooru.org/api/v1/json/search/images"; + uri = uri.SetQueryParam("q", "fluttershy"); + + var searchResult = await uri.GetJsonAsync(); + + searchResult.Should().NotBeNull(); + } + + [Fact] + [Trait(TestConstants.Category, TestConstants.DerpibooruCall)] + public async Task Search_WithDefaultExample_ReturnsResults() + { + var searchResult = await _client + .Search() + .Uri + .GetJsonAsync(); + + searchResult.Should().NotBeNull(); + searchResult.Images.Length.Should().BeGreaterThan(0); + } + + [Fact] + [Trait(TestConstants.Category, TestConstants.DerpibooruCall)] + public async Task Search_ByTag_ReturnsResults() + { + const string Rarity = "rarity"; + const string TwilightSparkle = "twilight sparkle"; + var searchResult = await _client + .Search() + .WithQuery($"{Rarity} AND {TwilightSparkle}") + .Uri + .GetJsonAsync(); + + searchResult.Should().NotBeNull(); + searchResult.Images.Length.Should().BeGreaterThan(0); + searchResult.Images[0].Tags.Should().Contain(new string[] { Rarity, TwilightSparkle }); + } + + [Fact] + [Trait(TestConstants.Category, TestConstants.DerpibooruCall)] + public async Task Search_ByRandom_ReturnsResults() + { + var searchResult = await _client + .Search() + .SortBy("random") + .Uri + .GetJsonAsync(); + + var searchResult2 = await _client + .Search() + .SortBy("random") + .Uri + .GetJsonAsync(); + + searchResult.Should().NotBeNull(); + searchResult.Images.Length.Should().BeGreaterThan(0); + searchResult2.Should().NotBeNull(); + searchResult2.Images.Length.Should().BeGreaterThan(0); + searchResult.Should().NotBe(searchResult2); + searchResult.Images[0].Id.Should().NotBe(searchResult2.Images[0].Id); + } + + [Fact] + public void Search_WithApiKey_HasKeyParam() + { + const string ApiKey = "apikey"; + var derpiClient = new DerpiClient(ApiKey); + + var uri = derpiClient.Search().Uri; + + uri.Should().Contain($"key={ApiKey}"); + } + + [Fact] + public void Search_WithoutApiKey_HasNoKeyParam() + { + var derpiClient = new DerpiClient(); + + var uri = derpiClient.Search().Uri; + + uri.Should().NotContain("key="); + } } diff --git a/tests/Nullforce.Api.Derpibooru.Tests/UrlBuilder/Derpibooru/SearchTests.cs b/tests/Nullforce.Api.Derpibooru.Tests/UrlBuilder/Derpibooru/SearchTests.cs deleted file mode 100644 index 5df9423..0000000 --- a/tests/Nullforce.Api.Derpibooru.Tests/UrlBuilder/Derpibooru/SearchTests.cs +++ /dev/null @@ -1,107 +0,0 @@ -using Nullforce.Api.JsonModels.Philomena; -using Nullforce.Api.UrlBuilder.Derpibooru; - -namespace Nullforce.Api.Derpibooru.Tests.UrlBuilder.Derpibooru; - -public class SearchTests -{ - private readonly DerpiClient _client = new(); - - public SearchTests() - { - // Do this in Startup. All calls to the URI will use the same HttpClient instance. - FlurlHttp.ConfigureClient("https://derpibooru.org/api/v1/json", cli => cli - .WithHeaders(new - { - Accept = "application/json", - User_Agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.75 Safari/537.36" - })); - } - - [Fact] - [Trait(TestConstants.Category, TestConstants.DerpibooruCall)] - public async Task SearchRawUri() - { - var uri = "https://derpibooru.org/api/v1/json/search/images"; - uri = uri.SetQueryParam("q", "fluttershy"); - - var searchResult = await uri.GetJsonAsync(); - - searchResult.Should().NotBeNull(); - } - - [Fact] - [Trait(TestConstants.Category, TestConstants.DerpibooruCall)] - public async Task Search_WithDefaultExample_ReturnsResults() - { - var searchResult = await _client - .Search() - .Uri - .GetJsonAsync(); - - searchResult.Should().NotBeNull(); - searchResult.Images.Length.Should().BeGreaterThan(0); - } - - [Fact] - [Trait(TestConstants.Category, TestConstants.DerpibooruCall)] - public async Task Search_ByTag_ReturnsResults() - { - const string Rarity = "rarity"; - const string TwilightSparkle = "twilight sparkle"; - var searchResult = await _client - .Search() - .WithQuery($"{Rarity} AND {TwilightSparkle}") - .Uri - .GetJsonAsync(); - - searchResult.Should().NotBeNull(); - searchResult.Images.Length.Should().BeGreaterThan(0); - searchResult.Images[0].Tags.Should().Contain(new string[] { Rarity, TwilightSparkle }); - } - - [Fact] - [Trait(TestConstants.Category, TestConstants.DerpibooruCall)] - public async Task Search_ByRandom_ReturnsResults() - { - var searchResult = await _client - .Search() - .SortBy("random") - .Uri - .GetJsonAsync(); - - var searchResult2 = await _client - .Search() - .SortBy("random") - .Uri - .GetJsonAsync(); - - searchResult.Should().NotBeNull(); - searchResult.Images.Length.Should().BeGreaterThan(0); - searchResult2.Should().NotBeNull(); - searchResult2.Images.Length.Should().BeGreaterThan(0); - searchResult.Should().NotBe(searchResult2); - searchResult.Images[0].Id.Should().NotBe(searchResult2.Images[0].Id); - } - - [Fact] - public void Search_WithApiKey_HasKeyParam() - { - const string ApiKey = "apikey"; - var derpiClient = new DerpiClient(ApiKey); - - var uri = derpiClient.Search().Uri; - - uri.Should().Contain($"key={ApiKey}"); - } - - [Fact] - public void Search_WithoutApiKey_HasNoKeyParam() - { - var derpiClient = new DerpiClient(); - - var uri = derpiClient.Search().Uri; - - uri.Should().NotContain("key="); - } -} From 08d4aeca1f1c9a43441527d8412f8e7ed27767b9 Mon Sep 17 00:00:00 2001 From: nullforce Date: Sun, 14 Aug 2022 19:25:01 -0500 Subject: [PATCH 5/5] Update unit tests and fix per_page parameter --- src/UrlBuilder/Derpibooru/DerpiSearch.cs | 2 +- src/UrlBuilder/Twibooru/TwibooruSearch.cs | 2 +- .../DerpibooruGetFeaturedImageTests.cs | 4 +- .../Derpibooru/DerpibooruGetImageTests.cs | 43 ++----- .../Derpibooru/DerpibooruSearchTests.cs | 108 ++++-------------- .../Twibooru/TwibooruSearchTests.cs | 60 ++++------ 6 files changed, 62 insertions(+), 157 deletions(-) diff --git a/src/UrlBuilder/Derpibooru/DerpiSearch.cs b/src/UrlBuilder/Derpibooru/DerpiSearch.cs index 3284ecb..38f80af 100644 --- a/src/UrlBuilder/Derpibooru/DerpiSearch.cs +++ b/src/UrlBuilder/Derpibooru/DerpiSearch.cs @@ -146,7 +146,7 @@ public ISearch Page(int page) /// public ISearch PerPage(int limit) { - _uri = _uri.SetQueryParam("perpage", limit); + _uri = _uri.SetQueryParam("per_page", limit); return this; } } diff --git a/src/UrlBuilder/Twibooru/TwibooruSearch.cs b/src/UrlBuilder/Twibooru/TwibooruSearch.cs index 74289a7..d22c035 100644 --- a/src/UrlBuilder/Twibooru/TwibooruSearch.cs +++ b/src/UrlBuilder/Twibooru/TwibooruSearch.cs @@ -29,7 +29,7 @@ public ISearch Page(int page) public ISearch PerPage(int limit) { - _uri = _uri.SetQueryParam("perpage", limit); + _uri = _uri.SetQueryParam("per_page", limit); return this; } diff --git a/tests/Nullforce.Api.Derpibooru.Tests/UrlBuilder/Derpibooru/DerpibooruGetFeaturedImageTests.cs b/tests/Nullforce.Api.Derpibooru.Tests/UrlBuilder/Derpibooru/DerpibooruGetFeaturedImageTests.cs index 1cc66ad..4499fbf 100644 --- a/tests/Nullforce.Api.Derpibooru.Tests/UrlBuilder/Derpibooru/DerpibooruGetFeaturedImageTests.cs +++ b/tests/Nullforce.Api.Derpibooru.Tests/UrlBuilder/Derpibooru/DerpibooruGetFeaturedImageTests.cs @@ -9,9 +9,7 @@ public class DerpibooruGetFeaturedImageTests [Fact] public void GetFeaturedImage_BuildsUrl() { - var uri = _client - .GetFeaturedImage() - .Uri; + var uri = _client.GetFeaturedImage().Uri; uri.Should().Be("https://derpibooru.org/api/v1/json/images/featured"); } diff --git a/tests/Nullforce.Api.Derpibooru.Tests/UrlBuilder/Derpibooru/DerpibooruGetImageTests.cs b/tests/Nullforce.Api.Derpibooru.Tests/UrlBuilder/Derpibooru/DerpibooruGetImageTests.cs index b935da9..f2dd113 100644 --- a/tests/Nullforce.Api.Derpibooru.Tests/UrlBuilder/Derpibooru/DerpibooruGetImageTests.cs +++ b/tests/Nullforce.Api.Derpibooru.Tests/UrlBuilder/Derpibooru/DerpibooruGetImageTests.cs @@ -1,5 +1,4 @@ -using Nullforce.Api.JsonModels.Philomena; -using Nullforce.Api.UrlBuilder.Derpibooru; +using Nullforce.Api.UrlBuilder.Derpibooru; namespace Nullforce.Api.Derpibooru.Tests.UrlBuilder.Derpibooru; @@ -7,44 +6,22 @@ public class DerpibooruGetImageTests { private readonly DerpiClient _client = new (); - public DerpibooruGetImageTests() - { - // Do this in Startup. All calls to the URI will use the same HttpClient instance. - FlurlHttp.ConfigureClient("https://derpibooru.org/api/v1/json", cli => cli - .WithHeaders(new - { - Accept = "application/json", - User_Agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.75 Safari/537.36" - })); - } - [Fact] - [Trait(TestConstants.Category, TestConstants.DerpibooruCall)] - public async Task GetImage_WithId_ShouldReturnImageRoot() + public void GetImage_BuildsUrl() { - const int ImageId = 1; - - var imageRoot = await _client - .GetImage(ImageId) - .WithFilterId((int) DerpiSystemFilter.Default) - .Uri - .GetJsonAsync(); + var uri = _client.GetImage(1).Uri; - imageRoot.Should().NotBeNull(); - imageRoot.Image.Should().NotBeNull(); - imageRoot.Image.Id.Should().Be(ImageId); + uri.Should().Be("https://derpibooru.org/api/v1/json/images/1"); } [Fact] - [Trait(TestConstants.Category, TestConstants.DerpibooruCall)] - public async Task GetFeaturedImage_ShouldReturnImageRoot() + public void GetImage_WithFilterId_BuildsUrl() { - var imageRoot = await _client - .GetFeaturedImage() - .Uri - .GetJsonAsync(); + var uri = _client + .GetImage(1) + .WithFilterId(2) + .Uri; - imageRoot.Should().NotBeNull(); - imageRoot.Image.Should().NotBeNull(); + uri.Should().Contain("filter_id=2"); } } diff --git a/tests/Nullforce.Api.Derpibooru.Tests/UrlBuilder/Derpibooru/DerpibooruSearchTests.cs b/tests/Nullforce.Api.Derpibooru.Tests/UrlBuilder/Derpibooru/DerpibooruSearchTests.cs index 99081d1..372bdbd 100644 --- a/tests/Nullforce.Api.Derpibooru.Tests/UrlBuilder/Derpibooru/DerpibooruSearchTests.cs +++ b/tests/Nullforce.Api.Derpibooru.Tests/UrlBuilder/Derpibooru/DerpibooruSearchTests.cs @@ -1,4 +1,3 @@ -using Nullforce.Api.JsonModels.Philomena; using Nullforce.Api.UrlBuilder.Derpibooru; namespace Nullforce.Api.Derpibooru.Tests.UrlBuilder.Derpibooru; @@ -7,101 +6,42 @@ public class DerpibooruSearchTests { private readonly DerpiClient _client = new(); - public DerpibooruSearchTests() - { - // Do this in Startup. All calls to the URI will use the same HttpClient instance. - FlurlHttp.ConfigureClient("https://derpibooru.org/api/v1/json", cli => cli - .WithHeaders(new - { - Accept = "application/json", - User_Agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.75 Safari/537.36" - })); - } - [Fact] - [Trait(TestConstants.Category, TestConstants.DerpibooruCall)] - public async Task SearchRawUri() + public void Search_BuildsUrl() { - var uri = "https://derpibooru.org/api/v1/json/search/images"; - uri = uri.SetQueryParam("q", "fluttershy"); - - var searchResult = await uri.GetJsonAsync(); + var uri = _client.Search().Uri; - searchResult.Should().NotBeNull(); + uri.Should().Be("https://derpibooru.org/api/v1/json/search/images?q=%2A&sf=created_at&sd=desc"); } [Fact] - [Trait(TestConstants.Category, TestConstants.DerpibooruCall)] - public async Task Search_WithDefaultExample_ReturnsResults() + public void Search_WithKey_BuildsUrlWithKey() { - var searchResult = await _client - .Search() - .Uri - .GetJsonAsync(); + var uri = (new DerpiClient("apikey")).Search().Uri; - searchResult.Should().NotBeNull(); - searchResult.Images.Length.Should().BeGreaterThan(0); + uri.Should().Contain("key=apikey"); } [Fact] - [Trait(TestConstants.Category, TestConstants.DerpibooruCall)] - public async Task Search_ByTag_ReturnsResults() + public void Search_WithParameters_BuildsUrl() { - const string Rarity = "rarity"; - const string TwilightSparkle = "twilight sparkle"; - var searchResult = await _client - .Search() - .WithQuery($"{Rarity} AND {TwilightSparkle}") - .Uri - .GetJsonAsync(); - - searchResult.Should().NotBeNull(); - searchResult.Images.Length.Should().BeGreaterThan(0); - searchResult.Images[0].Tags.Should().Contain(new string[] { Rarity, TwilightSparkle }); - } - - [Fact] - [Trait(TestConstants.Category, TestConstants.DerpibooruCall)] - public async Task Search_ByRandom_ReturnsResults() - { - var searchResult = await _client - .Search() - .SortBy("random") - .Uri - .GetJsonAsync(); - - var searchResult2 = await _client + var uri = _client .Search() - .SortBy("random") - .Uri - .GetJsonAsync(); - - searchResult.Should().NotBeNull(); - searchResult.Images.Length.Should().BeGreaterThan(0); - searchResult2.Should().NotBeNull(); - searchResult2.Images.Length.Should().BeGreaterThan(0); - searchResult.Should().NotBe(searchResult2); - searchResult.Images[0].Id.Should().NotBe(searchResult2.Images[0].Id); - } - - [Fact] - public void Search_WithApiKey_HasKeyParam() - { - const string ApiKey = "apikey"; - var derpiClient = new DerpiClient(ApiKey); - - var uri = derpiClient.Search().Uri; - - uri.Should().Contain($"key={ApiKey}"); - } - - [Fact] - public void Search_WithoutApiKey_HasNoKeyParam() - { - var derpiClient = new DerpiClient(); - - var uri = derpiClient.Search().Uri; - - uri.Should().NotContain("key="); + .WithQuery("fluttershy") + .WithFilterId(1) + .SortBy("created_at") + .SortAscending() + .Page(1) + .PerPage(50) + .Uri; + + using var _ = new AssertionScope(); + + uri.Should().Contain("q=fluttershy") + .And.Contain("filter_id=1") + .And.Contain("sf=created_at") + .And.Contain("sd=asc") + .And.Contain("page=1") + .And.Contain("per_page=50"); } } diff --git a/tests/Nullforce.Api.Derpibooru.Tests/UrlBuilder/Twibooru/TwibooruSearchTests.cs b/tests/Nullforce.Api.Derpibooru.Tests/UrlBuilder/Twibooru/TwibooruSearchTests.cs index f4fda8d..ecf4735 100644 --- a/tests/Nullforce.Api.Derpibooru.Tests/UrlBuilder/Twibooru/TwibooruSearchTests.cs +++ b/tests/Nullforce.Api.Derpibooru.Tests/UrlBuilder/Twibooru/TwibooruSearchTests.cs @@ -1,58 +1,48 @@ -using Nullforce.Api.JsonModels.Twibooru; -using Nullforce.Api.UrlBuilder.Twibooru; +using Nullforce.Api.UrlBuilder.Twibooru; namespace Nullforce.Api.Derpibooru.Tests.UrlBuilder.Twibooru; public class TwibooruSearchTests { + private readonly TwibooruClient _client = new(); private readonly TwibooruSearch _search = new("https://twibooru.org/api/v3", string.Empty); - public TwibooruSearchTests() + [Fact] + public void Search_BuildsUrl() { - // Do this in Startup. All calls to the URI will use the same HttpClient instance. - FlurlHttp.ConfigureClient("https://derpibooru.org/api/v1/json", cli => cli - .WithHeaders(new - { - Accept = "application/json", - User_Agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.75 Safari/537.36" - })); + var uri = _client.Search().Uri; + + uri.Should().Be("https://twibooru.org/api/v3/search/posts?q=%2A&sf=created_at&sd=desc"); } [Fact] - public async Task Search_WithDefaults_ReturnsResults() + public void Search_WithKey_BuildsUrlWithKey() { - var uri = _search.Uri; - var json = await uri.GetStringAsync(); - var searchResult = JsonSerializer.Deserialize(json); - - uri.Should().Be("https://twibooru.org/api/v3/search/posts?q=%2A&sf=created_at&sd=desc"); + var uri = (new TwibooruClient("apikey")).Search().Uri; - searchResult.Should().NotBeNull(); - searchResult.JsonExtensionData.Should().BeNull(); - searchResult.Posts.Should().NotBeNull(); - searchResult.Total.Should().BeGreaterThanOrEqualTo(1); + uri.Should().Contain("key=apikey"); } [Fact] - public async Task Search_WithId_ReturnsResults() + public void Search_WithParameters_BuildsUrl() { - var uri = _search - .WithQuery("id:3") + var uri = _client + .Search() + .WithQuery("fluttershy") + .WithFilterId(1) + .SortBy("created_at") + .SortAscending() + .Page(1) + .PerPage(50) .Uri; - var json = await uri.GetStringAsync(); - var searchResult = JsonSerializer.Deserialize(json); using var _ = new AssertionScope(); - searchResult.Should().NotBeNull(); - searchResult.JsonExtensionData.Should().BeNull(); - - searchResult.Posts.Should().NotBeNull(); - searchResult.Posts.Should().HaveCount(1); - searchResult.Posts[0].MediaType.Should().Be("image"); - - searchResult.Total.Should().Be(1); + uri.Should().Contain("q=fluttershy") + .And.Contain("filter_id=1") + .And.Contain("sf=created_at") + .And.Contain("sd=asc") + .And.Contain("page=1") + .And.Contain("per_page=50"); } - - }