diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..cd967fc --- /dev/null +++ b/.dockerignore @@ -0,0 +1,25 @@ +**/.dockerignore +**/.env +**/.git +**/.gitignore +**/.project +**/.settings +**/.toolstarget +**/.vs +**/.vscode +**/.idea +**/*.*proj.user +**/*.dbmdl +**/*.jfm +**/azds.yaml +**/bin +**/charts +**/docker-compose* +**/Dockerfile* +**/node_modules +**/npm-debug.log +**/obj +**/secrets.dev.yaml +**/values.dev.yaml +LICENSE +README.md \ No newline at end of file diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index 0473985..c8617dc 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -1,9 +1,7 @@ -# This workflow will build a .NET project -# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-net - -name: .NET +name: .NET - Build NuGet and Publish on: + workflow_dispatch: push: branches: [ "main" ] pull_request: @@ -11,25 +9,66 @@ on: jobs: build: + name: Build and analyze + runs-on: windows-latest + env: + ProjectName: 'AStar.Dev.Admin.Api.Client.Sdk' + RepositoryName: 'astar-dev-admin-api-client-sdk' + steps: + - name: Set up JDK + uses: actions/setup-java@v4.4.0 + with: + java-version: 17 + distribution: 'zulu' - runs-on: ubuntu-latest + - name: Setup .NET + uses: actions/setup-dotnet@v4 + with: + dotnet-version: 9.0.x - steps: - - uses: actions/checkout@v4 - - - name: Setup .NET - uses: actions/setup-dotnet@v4 - with: - dotnet-version: 9.0.x - - - name: Delete nuget*.config files - run: rm -f nuget*.config - - - name: Restore dependencies - run: dotnet restore - - - name: Build - run: dotnet build --no-restore - - - name: Test - run: dotnet test --no-build --verbosity normal + - name: Checkout + uses: actions/checkout@v4.2.1 + with: + fetch-depth: 0 + + - name: Cache SonarCloud packages + uses: actions/cache@v4.2.3 + with: + path: ~\sonar\cache + key: ${{ runner.os }}-sonar + restore-keys: ${{ runner.os }}-sonar + + - name: Cache SonarCloud scanner + id: cache-sonar-scanner + uses: actions/cache@v4.2.3 + with: + path: .\.sonar\scanner + key: ${{ runner.os }}-sonar-scanner + restore-keys: ${{ runner.os }}-sonar-scanner + + - name: Install SonarCloud scanner + if: steps.cache-sonar-scanner.outputs.cache-hit != 'true' + shell: powershell + run: | + New-Item -Path .\.sonar\scanner -ItemType Directory + dotnet tool update dotnet-sonarscanner --tool-path .\.sonar\scanner + + - name: Build and analyze + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + shell: powershell + run: | + dotnet tool install --global dotnet-coverage + .\.sonar\scanner\dotnet-sonarscanner begin /k:"astar-development_${{ env.RepositoryName }}" /o:"astar-development" /d:sonar.token="${{ secrets.SONAR_TOKEN }}" /d:sonar.host.url="https://sonarcloud.io" /d:sonar.cs.vscoveragexml.reportsPaths=coverage.xml /d:sonar.scanner.scanAll=false + dotnet build --configuration Release + dotnet-coverage collect 'dotnet test --filter "FullyQualifiedName!~Acceptance.Tests"' -f xml -o 'coverage.xml' + .\.sonar\scanner\dotnet-sonarscanner end /d:sonar.token="${{ secrets.SONAR_TOKEN }}" + + - name: Pack NuGet package + if: github.ref == 'refs/heads/main' + run: dotnet pack .\src\${{ env.ProjectName }}\${{ env.ProjectName }}.csproj + + - name: Push to NuGet + if: github.ref == 'refs/heads/main' + run: dotnet nuget push "**\${{ env.ProjectName }}.*.nupkg" --api-key ${{secrets.nuget_api_key}} --skip-duplicate --source https://api.nuget.org/v3/index.json diff --git a/.idea/.idea.AStar.Dev.Admin.Api.Client.Sdk/.idea/.gitignore b/.idea/.idea.AStar.Dev.Admin.Api.Client.Sdk/.idea/.gitignore new file mode 100644 index 0000000..fbd23cc --- /dev/null +++ b/.idea/.idea.AStar.Dev.Admin.Api.Client.Sdk/.idea/.gitignore @@ -0,0 +1,13 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Rider ignored files +/contentModel.xml +/projectSettingsUpdater.xml +/modules.xml +/.idea.AStar.Dev.Admin.Api.Client.Sdk.iml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/.idea.AStar.Dev.Admin.Api.Client.Sdk/.idea/.name b/.idea/.idea.AStar.Dev.Admin.Api.Client.Sdk/.idea/.name new file mode 100644 index 0000000..c79273f --- /dev/null +++ b/.idea/.idea.AStar.Dev.Admin.Api.Client.Sdk/.idea/.name @@ -0,0 +1 @@ +AStar.Dev.Admin.Api.Client.Sdk \ No newline at end of file diff --git a/.idea/.idea.AStar.Dev.Admin.Api.Client.Sdk/.idea/indexLayout.xml b/.idea/.idea.AStar.Dev.Admin.Api.Client.Sdk/.idea/indexLayout.xml new file mode 100644 index 0000000..7b08163 --- /dev/null +++ b/.idea/.idea.AStar.Dev.Admin.Api.Client.Sdk/.idea/indexLayout.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/.idea.AStar.Dev.Admin.Api.Client.Sdk/.idea/vcs.xml b/.idea/.idea.AStar.Dev.Admin.Api.Client.Sdk/.idea/vcs.xml new file mode 100644 index 0000000..8306744 --- /dev/null +++ b/.idea/.idea.AStar.Dev.Admin.Api.Client.Sdk/.idea/vcs.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/AStar.Dev.Admin.Api.Client.Sdk.sln b/AStar.Dev.Admin.Api.Client.Sdk.sln new file mode 100644 index 0000000..a9dc473 --- /dev/null +++ b/AStar.Dev.Admin.Api.Client.Sdk.sln @@ -0,0 +1,47 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31903.59 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{F881F2A5-6B1D-4E4F-A698-C3D5E760E509}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{F205434D-6BE3-414B-A17D-A12F8E78C58F}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AStar.Dev.Admin.Api.Client.Sdk", "src\AStar.Dev.Admin.Api.Client.Sdk\AStar.Dev.Admin.Api.Client.Sdk.csproj", "{1A33B6F9-9126-43D5-962B-6BA2DBE5B052}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit", "test\AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit\AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit.csproj", "{20915888-5AEA-4918-8DE4-FBE77EFCC758}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".github", ".github", "{94A53025-23C4-4B9D-B015-B7CDBD1E2275}" + ProjectSection(SolutionItems) = preProject + .github\dependabot.yml = .github\dependabot.yml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflows", "workflows", "{790D531F-FFB9-4C8C-A861-C469CDF5DB9D}" + ProjectSection(SolutionItems) = preProject + .github\workflows\dotnet.yml = .github\workflows\dotnet.yml + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {1A33B6F9-9126-43D5-962B-6BA2DBE5B052} = {F881F2A5-6B1D-4E4F-A698-C3D5E760E509} + {20915888-5AEA-4918-8DE4-FBE77EFCC758} = {F205434D-6BE3-414B-A17D-A12F8E78C58F} + {790D531F-FFB9-4C8C-A861-C469CDF5DB9D} = {94A53025-23C4-4B9D-B015-B7CDBD1E2275} + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {1A33B6F9-9126-43D5-962B-6BA2DBE5B052}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1A33B6F9-9126-43D5-962B-6BA2DBE5B052}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1A33B6F9-9126-43D5-962B-6BA2DBE5B052}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1A33B6F9-9126-43D5-962B-6BA2DBE5B052}.Release|Any CPU.Build.0 = Release|Any CPU + {20915888-5AEA-4918-8DE4-FBE77EFCC758}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {20915888-5AEA-4918-8DE4-FBE77EFCC758}.Debug|Any CPU.Build.0 = Debug|Any CPU + {20915888-5AEA-4918-8DE4-FBE77EFCC758}.Release|Any CPU.ActiveCfg = Release|Any CPU + {20915888-5AEA-4918-8DE4-FBE77EFCC758}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/AStar.Dev.Example.sln.sln b/AStar.Dev.Example.sln.sln deleted file mode 100644 index be68fef..0000000 --- a/AStar.Dev.Example.sln.sln +++ /dev/null @@ -1,57 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.0.31903.59 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{ADD5430F-CD80-42C7-80DA-90048E210EE7}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{73794993-9898-4968-AF19-C3E7450C94E4}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AStar.Dev.Example.ClassLib", "src\AStar.Dev.Example.ClassLib\AStar.Dev.Example.ClassLib.csproj", "{A9C19332-40FE-4E24-A890-405D46CD72A5}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "end-to-end", "end-to-end", "{F1C7FB9E-2F0F-41C9-822A-7320339193CA}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "integration", "integration", "{D724595D-C6BC-4F31-9D2A-4F4707436F10}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "unit", "unit", "{10DD984D-6788-4E04-A89C-3270006F5C56}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AStar.Dev.Example.ClassLib.Tests.Unit", "test\unit\AStar.Dev.Example.ClassLib.Tests.Unit\AStar.Dev.Example.ClassLib.Tests.Unit.csproj", "{1D7D41F6-3866-4C00-A1BA-1675227FA9FA}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{E1CEEE40-22D0-4F7B-AB2B-A308F8DE6A54}" - ProjectSection(SolutionItems) = preProject - .editorconfig = .editorconfig - .gitignore = .gitignore - build-and-test.ps1 = build-and-test.ps1 - CodeMaid.config = CodeMaid.config - LICENSE = LICENSE - nuget.ci.config = nuget.ci.config - nuget.config = nuget.config - README.md = README.md - EndProjectSection -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {A9C19332-40FE-4E24-A890-405D46CD72A5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A9C19332-40FE-4E24-A890-405D46CD72A5}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A9C19332-40FE-4E24-A890-405D46CD72A5}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A9C19332-40FE-4E24-A890-405D46CD72A5}.Release|Any CPU.Build.0 = Release|Any CPU - {1D7D41F6-3866-4C00-A1BA-1675227FA9FA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {1D7D41F6-3866-4C00-A1BA-1675227FA9FA}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1D7D41F6-3866-4C00-A1BA-1675227FA9FA}.Release|Any CPU.ActiveCfg = Release|Any CPU - {1D7D41F6-3866-4C00-A1BA-1675227FA9FA}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {A9C19332-40FE-4E24-A890-405D46CD72A5} = {ADD5430F-CD80-42C7-80DA-90048E210EE7} - {F1C7FB9E-2F0F-41C9-822A-7320339193CA} = {73794993-9898-4968-AF19-C3E7450C94E4} - {D724595D-C6BC-4F31-9D2A-4F4707436F10} = {73794993-9898-4968-AF19-C3E7450C94E4} - {10DD984D-6788-4E04-A89C-3270006F5C56} = {73794993-9898-4968-AF19-C3E7450C94E4} - {1D7D41F6-3866-4C00-A1BA-1675227FA9FA} = {10DD984D-6788-4E04-A89C-3270006F5C56} - EndGlobalSection -EndGlobal diff --git a/AStar.ico b/AStar.ico new file mode 100644 index 0000000..0b9aea4 Binary files /dev/null and b/AStar.ico differ diff --git a/AStar.png b/AStar.png new file mode 100644 index 0000000..8cac0a1 Binary files /dev/null and b/AStar.png differ diff --git a/CodeMaid.config b/CodeMaid.config deleted file mode 100644 index 54f2ebe..0000000 --- a/CodeMaid.config +++ /dev/null @@ -1,82 +0,0 @@ - - - - -
- - - - - - <?xml version="1.0" encoding="utf-16"?> - <ArrayOfString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xmlns:xsd="http://www.w3.org/2001/XMLSchema"> - <string>ReSharper disable </string> - <string>ReSharper enable </string> - </ArrayOfString> - - - - True - - - 1 - - - False - - - True - - - True - - - 1 - - - 2 - - - True - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - True - - - 1 - - - - \ No newline at end of file diff --git a/nuget.ci.config b/nuget.ci.config deleted file mode 100644 index aa5beec..0000000 --- a/nuget.ci.config +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/nuget.config b/nuget.config deleted file mode 100644 index 782724b..0000000 --- a/nuget.config +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/src/AStar.Dev.Admin.Api.Client.Sdk/AStar.Dev.Admin.Api.Client.Sdk.csproj b/src/AStar.Dev.Admin.Api.Client.Sdk/AStar.Dev.Admin.Api.Client.Sdk.csproj new file mode 100644 index 0000000..a48272c --- /dev/null +++ b/src/AStar.Dev.Admin.Api.Client.Sdk/AStar.Dev.Admin.Api.Client.Sdk.csproj @@ -0,0 +1,65 @@ + + + + latest-recommended + AStar Developement, Jason Barden + AStar Development + AStar Developement, 2025 + This package contains the currently supported methods for interacting with the Admin API whilst abstracting the details.. + $(AssemblyName).xml + True + True + true + enable + True + true + enable + AStar.png + LICENSE + https://github.com/astar-development/ + Readme.md + Update. + True + git + https://github.com/astar-development/ + snupkg + net9.0 + AStar.Dev.Admin.Api.Client.Sdk + 3a340cb0-60ee-4e38-93ac-0f8829c7193d + 0.1.0 + + + + + + + + + + + + + + + + + + + + + + + + + + + True + 1701;1702; + + + + True + 1701;1702; + + + diff --git a/src/AStar.Dev.Admin.Api.Client.Sdk/AStar.Dev.Admin.Api.Client.Sdk.xml b/src/AStar.Dev.Admin.Api.Client.Sdk/AStar.Dev.Admin.Api.Client.Sdk.xml new file mode 100644 index 0000000..54d3e7e --- /dev/null +++ b/src/AStar.Dev.Admin.Api.Client.Sdk/AStar.Dev.Admin.Api.Client.Sdk.xml @@ -0,0 +1,333 @@ + + + + AStar.Dev.Admin.Api.Client.Sdk + + + + + The class. + + + + + The class. + + + + + + + + + + + The GetSiteConfigurationAsync method will get the User Configuration. + + The Site Configuration - populated or empty + + + + The GetModelsToIgnoreAsync method will get the models to ignore. + + A collection of 0 or more models to ignore + + + + The GetScrapeDirectoriesAsync method will get the Scrape Directories. + + The Scrape Directories - populated or empty + + + + The GetSearchConfigurationAsync method will get the Search Configuration. + + The Search Configuration - populated or empty + + + + The GetTagsToIgnoreAsync method will get the Tags to Ignore. + + A collection of 0 or more Tags to Ignore + + + + The class containing the current configuration settings. + + + + + Gets the Section Location for the API configuration from within the appSettings.Json file. + + + + + + + + + + + The class containing the project-specific constants. + + + + + Gets the Api Name. + + + + + The class. + + + + + Gets or sets the value of the Model to ignore completely. I know, shocking... + + + + + Returns this object in JSON format + + + This object serialized as a JSON object. + + + + + The class containing the Scrape Directories Configuration. + + + + + Gets or sets The ID of the configuration. + + + + + Gets or sets the Root Directory for everything - search and save. + + + + + Gets or sets the Base Save Directory for the saving post search - appended to the root directory. + + + + + Gets or sets the Base Directory for the search checks - appended to the root directory. + + + + + Gets or sets the Base Directory Famous for the search checks for famous people - appended to the root directory. + + + + + Gets or sets the default subdirectory name for the save - appended to the root directory. + + + + + The class containing the full Search Category definition + + + + + Gets or sets The ID of the search category. + + + + + Gets or sets the Order of the search category - i.e. which category should be 1st, 2nd, etc. + + + + + Gets or sets the Name of the category. + + + + + Gets or sets the Last Known Image Count. + + + + + Gets or sets the Last Page Visited number. + + + + + Gets or sets the Total Pages for the results. + + + + + The class containing the full Search Configuration. + + + + + Gets or sets The ID of the configuration. + + + + + Gets or sets the Base Url for the login and search. + + + + + Gets or sets the Login Url. + + + + + Gets or sets the Search Categories. + + + + + Gets or sets the default Search String. + + + + + Gets or sets the TopWallpapers something. + + + + + Gets or sets the Search String Prefix. + + + + + Gets or sets the Search StringSuffix. + + + + + Gets or sets the Subscriptions something. + + + + + Gets or sets the base Image Pause In Seconds. + + + + + Gets or sets the Starting Page Number. + + + + + Gets or sets the Total Pages for the New Subscription search. + + + + + Gets or sets the Use Headless to determine whether to run in headless mode or not. + + + + + Gets or sets the Subscriptions Starting Page Number. + + + + + Gets or sets the Subscriptions Total Pages. + + + + + Gets or sets the Top Wallpapers Total Pages. + + + + + Gets or sets the Top Wallpapers Starting Page Number. + + + + + The class containing Site Configuration. + + + + + Gets or sets The ID of the configuration + + + + + Gets or sets the Login Email Address + + + + + Gets or sets the Username + + + + + Gets or sets the Password + + + + + Gets or sets the Site Configuration Slug + + + + + Gets or sets the Base URL + + + + + Gets or sets the Login URL + + + + + The class. + + + + + Gets or sets the value of the tag to ignore. I know, shocking... + + + + + Gets or sets the Ignore Image property. When set to true, the image is ignored irrespective of any other + setting. + + + + + Returns this object in JSON format + + + This object serialized as a JSON object. + + + + + + + + + + + + + + + diff --git a/src/AStar.Dev.Admin.Api.Client.Sdk/AStar.ico b/src/AStar.Dev.Admin.Api.Client.Sdk/AStar.ico new file mode 100644 index 0000000..0b9aea4 Binary files /dev/null and b/src/AStar.Dev.Admin.Api.Client.Sdk/AStar.ico differ diff --git a/src/AStar.Dev.Admin.Api.Client.Sdk/AdminApi/AdminApiClient.cs b/src/AStar.Dev.Admin.Api.Client.Sdk/AdminApi/AdminApiClient.cs new file mode 100644 index 0000000..5ab246f --- /dev/null +++ b/src/AStar.Dev.Admin.Api.Client.Sdk/AdminApi/AdminApiClient.cs @@ -0,0 +1,105 @@ +using System.Net.Http.Json; +using System.Text.Json; +using AStar.Dev.Admin.Api.Client.Sdk.Models; +using AStar.Dev.Api.HealthChecks; +using AStar.Dev.Functional.Extensions; +using AStar.Dev.Logging.Extensions; +using AStar.Dev.Technical.Debt.Reporting; +using AStar.Dev.Utilities; +using Microsoft.Identity.Web; + +namespace AStar.Dev.Admin.Api.Client.Sdk.AdminApi; + +/// +/// The class. +/// +public sealed class AdminApiClient(HttpClient httpClient, ITokenAcquisition tokenAcquisitionService, ILoggerAstar logger) : IApiClient +{ + private static readonly JsonSerializerOptions JsonSerializerOptions = new(JsonSerializerDefaults.Web); + + /// + [Refactor(1,1,"Remove from the Interface")]public async Task GetHealthAsync(CancellationToken cancellationToken = default) + { + logger.LogHealthCheckStart(Constants.ApiName); + + try + { + var response = await httpClient.GetAsync("/health/ready", cancellationToken); + + return response.IsSuccessStatusCode + ? (await JsonSerializer.DeserializeAsync(await response.Content.ReadAsStreamAsync(cancellationToken), JsonSerializerOptions, cancellationToken))! + : logger.ReturnLoggedFailure(response, Constants.ApiName); + } + catch (HttpRequestException ex) + { + logger.LogException(ex); + + return new() { Status = $"Could not get a response from the {Constants.ApiName}." }; + } + } + + /// + public async Task> GetHealthCheckAsync(CancellationToken cancellationToken = new ()) + => await GetSafelyAsync("/health/ready?version=1.0"); + + /// + /// The GetSiteConfigurationAsync method will get the User Configuration. + /// + /// The Site Configuration - populated or empty + public async Task>> GetSiteConfigurationAsync() + => await GetSafelyAsync>("site-configurations?version=1.0"); + + /// + /// The GetModelsToIgnoreAsync method will get the models to ignore. + /// + /// A collection of 0 or more models to ignore + public async Task>> GetModelsToIgnoreAsync() + => await GetSafelyAsync>("models-to-ignore?version=1"); + + /// + /// The GetScrapeDirectoriesAsync method will get the Scrape Directories. + /// + /// The Scrape Directories - populated or empty + public async Task> GetScrapeDirectoriesAsync() + => await GetSafelyAsync("scrape-directories?version=1"); + + /// + /// The GetSearchConfigurationAsync method will get the Search Configuration. + /// + /// The Search Configuration - populated or empty + public async Task> GetSearchConfigurationAsync() + => await GetSafelyAsync("search-configuration?version=1"); + + /// + /// The GetTagsToIgnoreAsync method will get the Tags to Ignore. + /// + /// A collection of 0 or more Tags to Ignore + public async Task>> GetTagsToIgnoreAsync() + => await GetSafelyAsync>("search-configuration?version=1"); + + private async Task> GetSafelyAsync( string uri) + { + try + { + logger.LogApiCallStart(Constants.ApiName, uri); + var token = await tokenAcquisitionService.GetAccessTokenForUserAsync(["api://2ca26585-5929-4aae-86a7-a00c3fc2d061/ToDoList.Write"]); + + _ = httpClient.AddBearerToken(token); + var response = await httpClient.GetAsync(uri); + + if (!response.IsSuccessStatusCode) + { + return logger.ReturnLoggedFailure( Constants.ApiName, uri, response.ReasonPhrase ?? response.StatusCode.ToString()); + } + + var result = (await response.Content.ReadFromJsonAsync(Utilities.Constants.WebDeserialisationSettings))!; + return logger.ReturnLoggedSuccess(result, Constants.ApiName, "uri"); + } + catch(Exception ex) + { + logger.LogException(ex); + + return Result.Failure(ex.Message)!; + } + } +} \ No newline at end of file diff --git a/src/AStar.Dev.Admin.Api.Client.Sdk/AdminApi/AdminApiConfiguration.cs b/src/AStar.Dev.Admin.Api.Client.Sdk/AdminApi/AdminApiConfiguration.cs new file mode 100644 index 0000000..f591ca4 --- /dev/null +++ b/src/AStar.Dev.Admin.Api.Client.Sdk/AdminApi/AdminApiConfiguration.cs @@ -0,0 +1,23 @@ +using System.ComponentModel.DataAnnotations; +using AStar.Dev.Api.Client.Sdk.Shared; + +namespace AStar.Dev.Admin.Api.Client.Sdk.AdminApi; + +/// +/// The class containing the current configuration settings. +/// +public sealed class AdminApiConfiguration : IApiConfiguration +{ + /// + /// Gets the Section Location for the API configuration from within the appSettings.Json file. + /// + public const string SectionLocation = "apiConfiguration:adminApiConfiguration"; + + /// + [Required] + public Uri BaseUrl { get; set; } = new("https://not.set.com"); + + /// + [Required] + public required string[] Scopes { get; set; } +} \ No newline at end of file diff --git a/src/AStar.Dev.Admin.Api.Client.Sdk/Constants.cs b/src/AStar.Dev.Admin.Api.Client.Sdk/Constants.cs new file mode 100644 index 0000000..2d4d1df --- /dev/null +++ b/src/AStar.Dev.Admin.Api.Client.Sdk/Constants.cs @@ -0,0 +1,12 @@ +namespace AStar.Dev.Admin.Api.Client.Sdk; + +/// +/// The class containing the project-specific constants. +/// +public static class Constants +{ + /// + /// Gets the Api Name. + /// + public const string ApiName = "AStar.Dev.Admin.Api"; +} \ No newline at end of file diff --git a/src/AStar.Dev.Admin.Api.Client.Sdk/LICENSE b/src/AStar.Dev.Admin.Api.Client.Sdk/LICENSE new file mode 100644 index 0000000..0b1b024 --- /dev/null +++ b/src/AStar.Dev.Admin.Api.Client.Sdk/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 AStar Development, Jason Barden + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/src/AStar.Dev.Admin.Api.Client.Sdk/Models/ModelToIgnore.cs b/src/AStar.Dev.Admin.Api.Client.Sdk/Models/ModelToIgnore.cs new file mode 100644 index 0000000..51eba12 --- /dev/null +++ b/src/AStar.Dev.Admin.Api.Client.Sdk/Models/ModelToIgnore.cs @@ -0,0 +1,23 @@ +using AStar.Dev.Utilities; + +namespace AStar.Dev.Admin.Api.Client.Sdk.Models; + +/// +/// The class. +/// +public sealed class ModelToIgnore +{ + /// + /// Gets or sets the value of the Model to ignore completely. I know, shocking... + /// + public string Value { get; set; } = string.Empty; + + /// + /// Returns this object in JSON format + /// + /// + /// This object serialized as a JSON object. + /// + public override string ToString() + => this.ToJson(); +} \ No newline at end of file diff --git a/src/AStar.Dev.Admin.Api.Client.Sdk/Models/ScrapeDirectories.cs b/src/AStar.Dev.Admin.Api.Client.Sdk/Models/ScrapeDirectories.cs new file mode 100644 index 0000000..a6df0d3 --- /dev/null +++ b/src/AStar.Dev.Admin.Api.Client.Sdk/Models/ScrapeDirectories.cs @@ -0,0 +1,37 @@ +namespace AStar.Dev.Admin.Api.Client.Sdk.Models; + +/// +/// The class containing the Scrape Directories Configuration. +/// +public sealed class ScrapeDirectories +{ + /// + /// Gets or sets The ID of the configuration. + /// + public int Id { get; set; } + + /// + /// Gets or sets the Root Directory for everything - search and save. + /// + public string RootDirectory { get; set; } = string.Empty; + + /// + /// Gets or sets the Base Save Directory for the saving post search - appended to the root directory. + /// + public string BaseSaveDirectory { get; set; } = string.Empty; + + /// + /// Gets or sets the Base Directory for the search checks - appended to the root directory. + /// + public string BaseDirectory { get; set; } = string.Empty; + + /// + /// Gets or sets the Base Directory Famous for the search checks for famous people - appended to the root directory. + /// + public string BaseDirectoryFamous { get; set; } = string.Empty; + + /// + /// Gets or sets the default subdirectory name for the save - appended to the root directory. + /// + public string SubDirectoryName { get; set; } = string.Empty; +} \ No newline at end of file diff --git a/src/AStar.Dev.Admin.Api.Client.Sdk/Models/SearchCategory.cs b/src/AStar.Dev.Admin.Api.Client.Sdk/Models/SearchCategory.cs new file mode 100644 index 0000000..c8d85af --- /dev/null +++ b/src/AStar.Dev.Admin.Api.Client.Sdk/Models/SearchCategory.cs @@ -0,0 +1,37 @@ +namespace AStar.Dev.Admin.Api.Client.Sdk.Models; + +/// +/// The class containing the full Search Category definition +/// +public sealed class SearchCategory +{ + /// + /// Gets or sets The ID of the search category. + /// + public string Id { get; set; } = string.Empty; + + /// + /// Gets or sets the Order of the search category - i.e. which category should be 1st, 2nd, etc. + /// + public int Order { get; set; } + + /// + /// Gets or sets the Name of the category. + /// + public string Name { get; set; } = string.Empty; + + /// + /// Gets or sets the Last Known Image Count. + /// + public int LastKnownImageCount { get; set; } + + /// + /// Gets or sets the Last Page Visited number. + /// + public int LastPageVisited { get; set; } + + /// + /// Gets or sets the Total Pages for the results. + /// + public int TotalPages { get; set; } +} \ No newline at end of file diff --git a/src/AStar.Dev.Admin.Api.Client.Sdk/Models/SearchConfiguration.cs b/src/AStar.Dev.Admin.Api.Client.Sdk/Models/SearchConfiguration.cs new file mode 100644 index 0000000..7ad38b4 --- /dev/null +++ b/src/AStar.Dev.Admin.Api.Client.Sdk/Models/SearchConfiguration.cs @@ -0,0 +1,92 @@ +namespace AStar.Dev.Admin.Api.Client.Sdk.Models; + +/// +/// The class containing the full Search Configuration. +/// +public sealed class SearchConfiguration +{ + /// + /// Gets or sets The ID of the configuration. + /// + public int Id { get; set; } + + /// + /// Gets or sets the Base Url for the login and search. + /// + public string BaseUrl { get; set; } = string.Empty; + + /// + /// Gets or sets the Login Url. + /// + public string LoginUrl { get; set; } = string.Empty; + + /// + /// Gets or sets the Search Categories. + /// + public IList SearchCategories { get; set; } = []; + + /// + /// Gets or sets the default Search String. + /// + public string SearchString { get; set; } = string.Empty; + + /// + /// Gets or sets the TopWallpapers something. + /// + public string TopWallpapers { get; set; } = string.Empty; + + /// + /// Gets or sets the Search String Prefix. + /// + public string SearchStringPrefix { get; set; } = string.Empty; + + /// + /// Gets or sets the Search StringSuffix. + /// + public string SearchStringSuffix { get; set; } = string.Empty; + + /// + /// Gets or sets the Subscriptions something. + /// + public string Subscriptions { get; set; } = string.Empty; + + /// + /// Gets or sets the base Image Pause In Seconds. + /// + public int ImagePauseInSeconds { get; set; } + + /// + /// Gets or sets the Starting Page Number. + /// + public int StartingPageNumber { get; set; } + + /// + /// Gets or sets the Total Pages for the New Subscription search. + /// + public int TotalPages { get; set; } + + /// + /// Gets or sets the Use Headless to determine whether to run in headless mode or not. + /// + public bool UseHeadless { get; set; } + + /// + /// Gets or sets the Subscriptions Starting Page Number. + /// + public int SubscriptionsStartingPageNumber { get; set; } + + /// + /// Gets or sets the Subscriptions Total Pages. + /// + public int SubscriptionsTotalPages { get; set; } + + /// + /// Gets or sets the Top Wallpapers Total Pages. + /// + public int TopWallpapersTotalPages { get; set; } + + /// + /// Gets or sets the Top Wallpapers Starting Page Number. + /// + public int TopWallpapersStartingPageNumber { get; set; } +} \ No newline at end of file diff --git a/src/AStar.Dev.Admin.Api.Client.Sdk/Models/SiteConfiguration.cs b/src/AStar.Dev.Admin.Api.Client.Sdk/Models/SiteConfiguration.cs new file mode 100644 index 0000000..bfba4e2 --- /dev/null +++ b/src/AStar.Dev.Admin.Api.Client.Sdk/Models/SiteConfiguration.cs @@ -0,0 +1,42 @@ +namespace AStar.Dev.Admin.Api.Client.Sdk.Models; + +/// +/// The class containing Site Configuration. +/// +public sealed class SiteConfiguration +{ + /// + /// Gets or sets The ID of the configuration + /// + public int Id { get; set; } + + /// + /// Gets or sets the Login Email Address + /// + public string LoginEmailAddress { get; set; } = string.Empty; + + /// + /// Gets or sets the Username + /// + public string Username { get; set; } = string.Empty; + + /// + /// Gets or sets the Password + /// + public string Password { get; set; } = string.Empty; + + /// + /// Gets or sets the Site Configuration Slug + /// + public string SiteConfigurationSlug { get; set; } = string.Empty; + + /// + /// Gets or sets the Base URL + /// + public string BaseUrl { get; set; } = string.Empty; + + /// + /// Gets or sets the Login URL + /// + public string LoginUrl { get; set; } = string.Empty; +} \ No newline at end of file diff --git a/src/AStar.Dev.Admin.Api.Client.Sdk/Models/TagToIgnore.cs b/src/AStar.Dev.Admin.Api.Client.Sdk/Models/TagToIgnore.cs new file mode 100644 index 0000000..2b38a1a --- /dev/null +++ b/src/AStar.Dev.Admin.Api.Client.Sdk/Models/TagToIgnore.cs @@ -0,0 +1,29 @@ +using AStar.Dev.Utilities; + +namespace AStar.Dev.Admin.Api.Client.Sdk.Models; + +/// +/// The class. +/// +public sealed class TagToIgnore +{ + /// + /// Gets or sets the value of the tag to ignore. I know, shocking... + /// + public string Value { get; set; } = string.Empty; + + /// + /// Gets or sets the Ignore Image property. When set to true, the image is ignored irrespective of any other + /// setting. + /// + public bool IgnoreImage { get; set; } + + /// + /// Returns this object in JSON format + /// + /// + /// This object serialized as a JSON object. + /// + public override string ToString() + => this.ToJson(); +} \ No newline at end of file diff --git a/src/AStar.Dev.Admin.Api.Client.Sdk/Readme.md b/src/AStar.Dev.Admin.Api.Client.Sdk/Readme.md new file mode 100644 index 0000000..10a241f --- /dev/null +++ b/src/AStar.Dev.Admin.Api.Client.Sdk/Readme.md @@ -0,0 +1,24 @@ +# AStar.Dev.Admin.Api.Client.Sdk + +This NuGet package, as the name suggests, contains the Client SDK for accessing the AStar.Dev.Admin.Api + +Methods include calling the healthcheck endpoint and various configuration-related endpoints + +## GitHub build + +[![.NET - Build NuGet and Publish](https://github.com/astar-development/astar-dev-admin-api-client-sdk/actions/workflows/dotnet.yml/badge.svg)](https://github.com/astar-development/astar-dev-admin-api-client-sdk/actions/workflows/dotnet.yml) + +## SonarCloud Analysis Results + +[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=jbarden_astar-dev-admin-api-client-sdk&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=jbarden_astar-dev-admin-api-client-sdk) + +[![Bugs](https://sonarcloud.io/api/project_badges/measure?project=jbarden_astar-dev-admin-api-client-sdk&metric=bugs)](https://sonarcloud.io/summary/new_code?id=jbarden_astar-dev-admin-api-client-sdk) + +[![Security Rating](https://sonarcloud.io/api/project_badges/measure?project=jbarden_astar-dev-admin-api-client-sdk&metric=security_rating)](https://sonarcloud.io/summary/new_code?id=jbarden_astar-dev-admin-api-client-sdk) + +[![Vulnerabilities](https://sonarcloud.io/api/project_badges/measure?project=jbarden_astar-dev-admin-api-client-sdk&metric=vulnerabilities)](https://sonarcloud.io/summary/new_code?id=jbarden_astar-dev-admin-api-client-sdk) + +[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=jbarden_astar-dev-admin-api-client-sdk&metric=coverage)](https://sonarcloud.io/summary/new_code?id=jbarden_astar-dev-admin-api-client-sdk) + +[![Code Smells](https://sonarcloud.io/api/project_badges/measure?project=jbarden_astar-dev-admin-api-client-sdk&metric=code_smells)](https://sonarcloud.io/summary/new_code?id=jbarden_astar-dev-admin-api-client-sdk) + diff --git a/src/AStar.Dev.Admin.Api.Client.Sdk/ServiceCollectionExtensions.cs b/src/AStar.Dev.Admin.Api.Client.Sdk/ServiceCollectionExtensions.cs new file mode 100644 index 0000000..a8a08d9 --- /dev/null +++ b/src/AStar.Dev.Admin.Api.Client.Sdk/ServiceCollectionExtensions.cs @@ -0,0 +1,45 @@ +using System.Net.Mime; +using AStar.Dev.Admin.Api.Client.Sdk.AdminApi; +using AStar.Dev.Api.HealthChecks; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; +using Microsoft.Identity.Web; + +namespace AStar.Dev.Admin.Api.Client.Sdk; + +/// +/// +public static class ServiceCollectionExtensions +{ + /// + /// + /// + /// + /// + public static IServiceCollection AddAdminApiClient(this IServiceCollection services, IConfiguration configuration) + { + var configurationSection = configuration.GetSection(AdminApiConfiguration.SectionLocation); + + _ = services.AddOptions() + .Bind(configurationSection) + .ValidateDataAnnotations() + .ValidateOnStart(); + + _ = services.AddScoped(); + + _ = services.AddHttpClient() + .ConfigureHttpClient((serviceProvider, client) => + { + client.BaseAddress = serviceProvider + .GetRequiredService>().Value + .BaseUrl; + + client.DefaultRequestHeaders.Accept.Add(new(MediaTypeNames.Application.Json)); + }); + + // _ = services.AddDownstreamApi(nameof(AdminApiClient), configuration.GetSection(AdminApiConfiguration.SectionLocation)); + + return services; + } +} \ No newline at end of file diff --git a/src/AStar.Dev.Example.ClassLib/AStar.Dev.Example.ClassLib.csproj b/src/AStar.Dev.Example.ClassLib/AStar.Dev.Example.ClassLib.csproj deleted file mode 100644 index 125f4c9..0000000 --- a/src/AStar.Dev.Example.ClassLib/AStar.Dev.Example.ClassLib.csproj +++ /dev/null @@ -1,9 +0,0 @@ - - - - net9.0 - enable - enable - - - diff --git a/src/AStar.Dev.Example.ClassLib/Class1.cs b/src/AStar.Dev.Example.ClassLib/Class1.cs deleted file mode 100644 index 27e9361..0000000 --- a/src/AStar.Dev.Example.ClassLib/Class1.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace AStar.Dev.Example.ClassLib; - -public class Class1 -{ - -} diff --git a/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit.csproj b/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit.csproj new file mode 100644 index 0000000..7ef1293 --- /dev/null +++ b/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit.csproj @@ -0,0 +1,58 @@ + + + + net9.0 + enable + enable + false + AStar.Dev.Admin.Api.Client.Sdk + True + latest-recommended + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + + + + + + PreserveNewest + + + + + True + 1701;1702;IDE0058; + + + + True + 1701;1702;IDE0058; + + + diff --git a/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/AdminApi/AdminApiClientGetModelToIgnoreShould.cs b/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/AdminApi/AdminApiClientGetModelToIgnoreShould.cs new file mode 100644 index 0000000..df5a011 --- /dev/null +++ b/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/AdminApi/AdminApiClientGetModelToIgnoreShould.cs @@ -0,0 +1,41 @@ +using AStar.Dev.Admin.Api.Client.Sdk.Helpers; +using AStar.Dev.Admin.Api.Client.Sdk.MockMessageHandlers; +using JetBrains.Annotations; + +namespace AStar.Dev.Admin.Api.Client.Sdk.AdminApi; + +[TestSubject(typeof(AdminApiClient))] +public class AdminApiClientGetModelToIgnoreShould +{ + [Fact] + public async Task ReturnExpectedFailureFromGetModelsToIgnoreAsyncWhenTheApiIsUnreachable() + { + var handler = new MockHttpRequestExceptionErrorHttpMessageHandler(); + var sut = AdminApiClientFactory.Create(handler); + + var response = await sut.GetModelsToIgnoreAsync(); + + response.IsFailure.ShouldBeTrue(); + } + + [Fact] + public async Task ReturnExpectedFailureMessageFromGetModelsToIgnoreAsyncWhenCheckFails() + { + var sut = AdminApiClientFactory.CreateInternalServerErrorClient("ModelsToIgnore"); + + var response = await sut.GetModelsToIgnoreAsync(); + + response.IsFailure.ShouldBeTrue(); + } + + [Fact] + public async Task ReturnExpectedMessageFromGetModelsToIgnoreAsyncWhenCheckSucceeds() + { + var handler = new MockSuccessHttpMessageHandler("ModelsToIgnore"); + var sut = AdminApiClientFactory.Create(handler); + + var response = await sut.GetModelsToIgnoreAsync(); + + response.IsSuccess.ShouldBeTrue(); + } +} \ No newline at end of file diff --git a/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/AdminApi/AdminApiClientGetScrapeDirectoriesShould.cs b/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/AdminApi/AdminApiClientGetScrapeDirectoriesShould.cs new file mode 100644 index 0000000..5995e63 --- /dev/null +++ b/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/AdminApi/AdminApiClientGetScrapeDirectoriesShould.cs @@ -0,0 +1,41 @@ +using AStar.Dev.Admin.Api.Client.Sdk.Helpers; +using AStar.Dev.Admin.Api.Client.Sdk.MockMessageHandlers; +using JetBrains.Annotations; + +namespace AStar.Dev.Admin.Api.Client.Sdk.AdminApi; + +[TestSubject(typeof(AdminApiClient))] +public class AdminApiClientGetScrapeDirectoriesShould +{ + [Fact] + public async Task ReturnExpectedFailureFromGetScrapeDirectoriesAsyncWhenTheApiIsUnreachable() + { + var handler = new MockHttpRequestExceptionErrorHttpMessageHandler(); + var sut = AdminApiClientFactory.Create(handler); + + var response = await sut.GetScrapeDirectoriesAsync(); + + response.IsFailure.ShouldBeTrue(); + } + + [Fact] + public async Task ReturnExpectedFailureMessageFromGetScrapeDirectoriesAsyncWhenCheckFails() + { + var sut = AdminApiClientFactory.CreateInternalServerErrorClient("ScrapeDirectories"); + + var response = await sut.GetScrapeDirectoriesAsync(); + + response.IsFailure.ShouldBeTrue(); + } + + [Fact] + public async Task ReturnExpectedMessageFromGetScrapeDirectoriesAsyncWhenCheckSucceeds() + { + var handler = new MockSuccessHttpMessageHandler("ScrapeDirectories"); + var sut = AdminApiClientFactory.Create(handler); + + var response = await sut.GetScrapeDirectoriesAsync(); + + response.IsSuccess.ShouldBeTrue(); + } +} \ No newline at end of file diff --git a/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/AdminApi/AdminApiClientGetSearchConfigurationShould.cs b/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/AdminApi/AdminApiClientGetSearchConfigurationShould.cs new file mode 100644 index 0000000..12c8546 --- /dev/null +++ b/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/AdminApi/AdminApiClientGetSearchConfigurationShould.cs @@ -0,0 +1,41 @@ +using AStar.Dev.Admin.Api.Client.Sdk.Helpers; +using AStar.Dev.Admin.Api.Client.Sdk.MockMessageHandlers; +using JetBrains.Annotations; + +namespace AStar.Dev.Admin.Api.Client.Sdk.AdminApi; + +[TestSubject(typeof(AdminApiClient))] +public class AdminApiClientSearchConfigurationShould +{ + [Fact] + public async Task ReturnExpectedFailureFromGetSearchConfigurationAsyncWhenTheApiIsUnreachable() + { + var handler = new MockHttpRequestExceptionErrorHttpMessageHandler(); + var sut = AdminApiClientFactory.Create(handler); + + var response = await sut.GetSearchConfigurationAsync(); + + response.IsFailure.ShouldBeTrue(); + } + + [Fact] + public async Task ReturnExpectedFailureMessageFromGetSearchConfigurationAsyncWhenCheckFails() + { + var sut = AdminApiClientFactory.CreateInternalServerErrorClient("SearchConfiguration"); + + var response = await sut.GetSearchConfigurationAsync(); + + response.IsFailure.ShouldBeTrue(); + } + + [Fact] + public async Task ReturnExpectedMessageFromGetSearchConfigurationAsyncWhenCheckSucceeds() + { + var handler = new MockSuccessHttpMessageHandler("SearchConfigurations"); + var sut = AdminApiClientFactory.Create(handler); + + var response = await sut.GetSearchConfigurationAsync(); + + response.IsSuccess.ShouldBeTrue(); + } +} \ No newline at end of file diff --git a/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/AdminApi/AdminApiClientGetSiteConfigurationShould.cs b/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/AdminApi/AdminApiClientGetSiteConfigurationShould.cs new file mode 100644 index 0000000..834c5d6 --- /dev/null +++ b/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/AdminApi/AdminApiClientGetSiteConfigurationShould.cs @@ -0,0 +1,41 @@ +using AStar.Dev.Admin.Api.Client.Sdk.Helpers; +using AStar.Dev.Admin.Api.Client.Sdk.MockMessageHandlers; +using JetBrains.Annotations; + +namespace AStar.Dev.Admin.Api.Client.Sdk.AdminApi; + +[TestSubject(typeof(AdminApiClient))] +public class AdminApiClientGetSiteConfigurationShould +{ + [Fact] + public async Task ReturnExpectedFailureFromGetSiteConfigurationAsyncWhenTheApiIsUnreachable() + { + var handler = new MockHttpRequestExceptionErrorHttpMessageHandler(); + var sut = AdminApiClientFactory.Create(handler); + + var response = await sut.GetSiteConfigurationAsync(); + + response.IsFailure.ShouldBeTrue(); + } + + [Fact] + public async Task ReturnExpectedFailureMessageFromGetSiteConfigurationAsyncWhenCheckFails() + { + var sut = AdminApiClientFactory.CreateInternalServerErrorClient("SiteConfiguration"); + + var response = await sut.GetSiteConfigurationAsync(); + + response.IsFailure.ShouldBeTrue(); + } + + [Fact] + public async Task ReturnExpectedMessageFromGetSiteConfigurationAsyncWhenCheckSucceeds() + { + var handler = new MockSuccessHttpMessageHandler("SiteConfigurations"); + var sut = AdminApiClientFactory.Create(handler); + + var response = await sut.GetSiteConfigurationAsync(); + + response.IsSuccess.ShouldBeTrue(); + } +} \ No newline at end of file diff --git a/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/AdminApi/AdminApiClientHealthChecksShould.cs b/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/AdminApi/AdminApiClientHealthChecksShould.cs new file mode 100644 index 0000000..0a761fd --- /dev/null +++ b/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/AdminApi/AdminApiClientHealthChecksShould.cs @@ -0,0 +1,54 @@ +using AStar.Dev.Admin.Api.Client.Sdk.Helpers; +using AStar.Dev.Admin.Api.Client.Sdk.MockMessageHandlers; +using JetBrains.Annotations; + +namespace AStar.Dev.Admin.Api.Client.Sdk.AdminApi; + +[TestSubject(typeof(AdminApiClient))] +public class AdminApiClientHealthChecksShould +{ + [Fact] + public async Task ReturnExpectedFailureFromGetHealthAsyncWhenTheApiIsUnreachableVersion2() + { + var handler = new MockHttpRequestExceptionErrorHttpMessageHandler(); + var sut = AdminApiClientFactory.Create(handler); + + var response = await sut.GetHealthCheckAsync(); + + response.IsFailure.ShouldBeTrue(); + response.Value?.Description.ShouldBe("Unable to retrieve the description of the Health Status"); + response.Value?.Status.ShouldBe("Could not get a response from the AStar.Dev.Admin.Api."); + } + + [Fact] + public async Task ReturnExpectedFailureFromGetHealthAsyncWhenTheApiIsUnreachable() + { + var handler = new MockHttpRequestExceptionErrorHttpMessageHandler(); + var sut = AdminApiClientFactory.Create(handler); + + var response = await sut.GetHealthAsync(); + + response.Status.ShouldBe("Could not get a response from the AStar.Dev.Admin.Api."); + } + + [Fact] + public async Task ReturnExpectedFailureMessageFromGetHealthAsyncWhenCheckFails() + { + var sut = AdminApiClientFactory.CreateInternalServerErrorClient("Health Check failed."); + + var response = await sut.GetHealthAsync(); + + response.Status.ShouldBe("Health Check failed - Internal Server Error."); + } + + [Fact] + public async Task ReturnExpectedMessageFromGetHealthAsyncWhenCheckSucceeds() + { + var handler = new MockSuccessHttpMessageHandler("Health"); + var sut = AdminApiClientFactory.Create(handler); + + var response = await sut.GetHealthAsync(); + + response.Status.ShouldBe("OK"); + } +} \ No newline at end of file diff --git a/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/AdminApi/AdminApiClientTagsToIgnoreShould.cs b/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/AdminApi/AdminApiClientTagsToIgnoreShould.cs new file mode 100644 index 0000000..ee70c13 --- /dev/null +++ b/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/AdminApi/AdminApiClientTagsToIgnoreShould.cs @@ -0,0 +1,41 @@ +using AStar.Dev.Admin.Api.Client.Sdk.Helpers; +using AStar.Dev.Admin.Api.Client.Sdk.MockMessageHandlers; +using JetBrains.Annotations; + +namespace AStar.Dev.Admin.Api.Client.Sdk.AdminApi; + +[TestSubject(typeof(AdminApiClient))] +public class AdminApiClientTagsToIgnoreShould +{ + [Fact] + public async Task ReturnExpectedFailureFromGetTagsToIgnoreAsyncWhenTheApiIsUnreachable() + { + var handler = new MockHttpRequestExceptionErrorHttpMessageHandler(); + var sut = AdminApiClientFactory.Create(handler); + + var response = await sut.GetTagsToIgnoreAsync(); + + response.IsFailure.ShouldBeTrue(); + } + + [Fact] + public async Task ReturnExpectedFailureMessageFromGetTagsToIgnoreAsyncWhenCheckFails() + { + var sut = AdminApiClientFactory.CreateInternalServerErrorClient("tags-to-ignore"); + + var response = await sut.GetTagsToIgnoreAsync(); + + response.IsFailure.ShouldBeTrue(); + } + + [Fact] + public async Task ReturnExpectedMessageFromGetTagsToIgnoreAsyncWhenCheckSucceeds() + { + var handler = new MockSuccessHttpMessageHandler("TagToIgnore"); + var sut = AdminApiClientFactory.Create(handler); + + var response = await sut.GetTagsToIgnoreAsync(); + + response.IsSuccess.ShouldBeTrue(); + } +} \ No newline at end of file diff --git a/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/AdminApi/AdminApiConfigurationShould.ContainTheExpectedProperties.approved.txt b/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/AdminApi/AdminApiConfigurationShould.ContainTheExpectedProperties.approved.txt new file mode 100644 index 0000000..b88b0fc --- /dev/null +++ b/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/AdminApi/AdminApiConfigurationShould.ContainTheExpectedProperties.approved.txt @@ -0,0 +1,6 @@ +{ + "baseUrl": "https://www.example.com", + "scopes": [ + "Not Relevant Here" + ] +} \ No newline at end of file diff --git a/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/AdminApi/AdminApiConfigurationShould.cs b/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/AdminApi/AdminApiConfigurationShould.cs new file mode 100644 index 0000000..eca381e --- /dev/null +++ b/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/AdminApi/AdminApiConfigurationShould.cs @@ -0,0 +1,12 @@ +using AStar.Dev.Utilities; +using JetBrains.Annotations; + +namespace AStar.Dev.Admin.Api.Client.Sdk.AdminApi; + +[TestSubject(typeof(AdminApiConfiguration))] +public class AdminApiConfigurationShould +{ + [Fact] + public void ContainTheExpectedProperties() + => new AdminApiConfiguration { Scopes = ["Not Relevant Here"], BaseUrl = new ("https://www.example.com") }.ToJson().ShouldMatchApproved(); +} \ No newline at end of file diff --git a/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/ConstantsShould.cs b/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/ConstantsShould.cs new file mode 100644 index 0000000..d4def37 --- /dev/null +++ b/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/ConstantsShould.cs @@ -0,0 +1,12 @@ +using JetBrains.Annotations; + +namespace AStar.Dev.Admin.Api.Client.Sdk; + +[TestSubject(typeof(Constants))] +public class ConstantsShould +{ + [Fact] + public void METHOD() + { + } +} \ No newline at end of file diff --git a/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/Helpers/AdminApiClientFactory.cs b/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/Helpers/AdminApiClientFactory.cs new file mode 100644 index 0000000..9ab37d7 --- /dev/null +++ b/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/Helpers/AdminApiClientFactory.cs @@ -0,0 +1,30 @@ +using AStar.Dev.Admin.Api.Client.Sdk.AdminApi; +using AStar.Dev.Admin.Api.Client.Sdk.MockMessageHandlers; +using AStar.Dev.Logging.Extensions; +using Microsoft.Identity.Web; +using NSubstitute; + +namespace AStar.Dev.Admin.Api.Client.Sdk.Helpers; + +internal static class AdminApiClientFactory +{ + private const string IrrelevantUrl = "https://doesnot.matter.com"; + private static readonly ILoggerAstar DummyLogger = Substitute.For>(); + + public static AdminApiClient Create(HttpMessageHandler mockHttpMessageHandler) + { + var tokenAcquisitionServiceMock = Substitute.For(); + var httpClient = new HttpClient(mockHttpMessageHandler) { BaseAddress = new(IrrelevantUrl) }; + + return new(httpClient, tokenAcquisitionServiceMock, DummyLogger); + } + + public static AdminApiClient CreateInternalServerErrorClient(string errorMessage) + { + var tokenAcquisitionServiceMock = Substitute.For(); + var handler = new MockInternalServerErrorHttpMessageHandler(errorMessage); + var httpClient = new HttpClient(handler) { BaseAddress = new(IrrelevantUrl) }; + + return new(httpClient, tokenAcquisitionServiceMock, DummyLogger); + } +} \ No newline at end of file diff --git a/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/MockMessageHandlers/MockDeletionSuccessHttpMessageHandler.cs b/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/MockMessageHandlers/MockDeletionSuccessHttpMessageHandler.cs new file mode 100644 index 0000000..6763575 --- /dev/null +++ b/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/MockMessageHandlers/MockDeletionSuccessHttpMessageHandler.cs @@ -0,0 +1,9 @@ +using System.Net; + +namespace AStar.Dev.Admin.Api.Client.Sdk.MockMessageHandlers; + +public sealed class MockDeletionSuccessHttpMessageHandler : HttpMessageHandler +{ + protected override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) + => Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK) { Content = new StringContent("Marked for deletion.") }); +} \ No newline at end of file diff --git a/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/MockMessageHandlers/MockHttpRequestExceptionErrorHttpMessageHandler.cs b/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/MockMessageHandlers/MockHttpRequestExceptionErrorHttpMessageHandler.cs new file mode 100644 index 0000000..c95a8e3 --- /dev/null +++ b/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/MockMessageHandlers/MockHttpRequestExceptionErrorHttpMessageHandler.cs @@ -0,0 +1,7 @@ +namespace AStar.Dev.Admin.Api.Client.Sdk.MockMessageHandlers; + +public sealed class MockHttpRequestExceptionErrorHttpMessageHandler : HttpMessageHandler +{ + protected override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) + => throw new HttpRequestException(); +} \ No newline at end of file diff --git a/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/MockMessageHandlers/MockInternalServerErrorHttpMessageHandler.cs b/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/MockMessageHandlers/MockInternalServerErrorHttpMessageHandler.cs new file mode 100644 index 0000000..f991fc0 --- /dev/null +++ b/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/MockMessageHandlers/MockInternalServerErrorHttpMessageHandler.cs @@ -0,0 +1,9 @@ +using System.Net; + +namespace AStar.Dev.Admin.Api.Client.Sdk.MockMessageHandlers; + +public sealed class MockInternalServerErrorHttpMessageHandler(string errorMessage) : HttpMessageHandler +{ + protected override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) + => Task.FromResult(new HttpResponseMessage(HttpStatusCode.InternalServerError) { Content = new StringContent(errorMessage) }); +} \ No newline at end of file diff --git a/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/MockMessageHandlers/MockSuccessHttpMessageHandler.cs b/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/MockMessageHandlers/MockSuccessHttpMessageHandler.cs new file mode 100644 index 0000000..6dcb797 --- /dev/null +++ b/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/MockMessageHandlers/MockSuccessHttpMessageHandler.cs @@ -0,0 +1,49 @@ +using System.Net; +using System.Text.Json; +using AStar.Dev.Admin.Api.Client.Sdk.Models; +using AStar.Dev.Api.HealthChecks; + +namespace AStar.Dev.Admin.Api.Client.Sdk.MockMessageHandlers; + +public sealed class MockSuccessHttpMessageHandler(string responseRequired) : HttpMessageHandler +{ + public int Counter { get; set; } + + protected override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) + { + HttpContent content; + +#pragma warning disable IDE0045 // Convert to conditional expression + if(responseRequired == "SiteConfigurations") + { + content = new StringContent(JsonSerializer.Serialize(new List { new () } )); + } + else if(responseRequired == "SiteConfiguration") + { + content = new StringContent(JsonSerializer.Serialize(new SiteConfiguration())); + } + else if(responseRequired == "SearchConfiguration") + { + content = new StringContent(JsonSerializer.Serialize(new List { new () } )); + } + else if(responseRequired == "TagToIgnore") + { + content = new StringContent(JsonSerializer.Serialize(new List { new () } )); + } + else if(responseRequired == "ModelsToIgnore") + { + content = new StringContent(JsonSerializer.Serialize(new List { new () } )); + } + else if (responseRequired == "Health") + { + content = new StringContent(JsonSerializer.Serialize(new HealthStatusResponse { Status = "OK" })); + } + else + { + content = new StringContent(JsonSerializer.Serialize(new HealthStatusResponse { Status = "NotSureYet" })); + } +#pragma warning restore IDE0045 // Convert to conditional expression + + return Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK) { Content = content }); + } +} \ No newline at end of file diff --git a/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/MockMessageHandlers/MockSuccessMessageWithValue0HttpMessageHandler.cs b/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/MockMessageHandlers/MockSuccessMessageWithValue0HttpMessageHandler.cs new file mode 100644 index 0000000..9246885 --- /dev/null +++ b/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/MockMessageHandlers/MockSuccessMessageWithValue0HttpMessageHandler.cs @@ -0,0 +1,10 @@ +using System.Net; + +namespace AStar.Dev.Admin.Api.Client.Sdk.MockMessageHandlers; + +public sealed class MockSuccessMessageWithValue0HttpMessageHandler : HttpMessageHandler +{ + protected override Task SendAsync(HttpRequestMessage request, + CancellationToken cancellationToken) + => Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK) { Content = new StringContent("0") }); +} \ No newline at end of file diff --git a/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/Models/ModelToIgnoreShould.ContainTheExpectedProperties.approved.txt b/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/Models/ModelToIgnoreShould.ContainTheExpectedProperties.approved.txt new file mode 100644 index 0000000..90f112b --- /dev/null +++ b/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/Models/ModelToIgnoreShould.ContainTheExpectedProperties.approved.txt @@ -0,0 +1,3 @@ +{ + "value": "Not Relevant Here" +} \ No newline at end of file diff --git a/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/Models/ModelToIgnoreShould.cs b/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/Models/ModelToIgnoreShould.cs new file mode 100644 index 0000000..ce30d3f --- /dev/null +++ b/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/Models/ModelToIgnoreShould.cs @@ -0,0 +1,12 @@ +using AStar.Dev.Utilities; +using JetBrains.Annotations; + +namespace AStar.Dev.Admin.Api.Client.Sdk.Models; + +[TestSubject(typeof(ModelToIgnore))] +public class ModelToIgnoreShould +{ + [Fact] + public void ContainTheExpectedProperties() + => new ModelToIgnore { Value = "Not Relevant Here" }.ToJson().ShouldMatchApproved(); +} \ No newline at end of file diff --git a/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/Models/ScrapeDirectoriesShould.ContainTheExpectedProperties.approved.txt b/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/Models/ScrapeDirectoriesShould.ContainTheExpectedProperties.approved.txt new file mode 100644 index 0000000..c97e70e --- /dev/null +++ b/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/Models/ScrapeDirectoriesShould.ContainTheExpectedProperties.approved.txt @@ -0,0 +1,8 @@ +{ + "id": 1, + "rootDirectory": "Root Directory Not Relevant Here", + "baseSaveDirectory": "Base Save Directory Not Relevant Here", + "baseDirectory": "Base Directory Not Relevant Here", + "baseDirectoryFamous": "Base Directory Famous Not Relevant Here", + "subDirectoryName": "Sub Directory Not Relevant Here" +} \ No newline at end of file diff --git a/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/Models/ScrapeDirectoriesShould.cs b/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/Models/ScrapeDirectoriesShould.cs new file mode 100644 index 0000000..7705ce3 --- /dev/null +++ b/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/Models/ScrapeDirectoriesShould.cs @@ -0,0 +1,22 @@ +using AStar.Dev.Utilities; +using JetBrains.Annotations; + +namespace AStar.Dev.Admin.Api.Client.Sdk.Models; + +[TestSubject(typeof(ScrapeDirectories))] +public class ScrapeDirectoriesShould +{ + [Fact] + public void ContainTheExpectedProperties() + => new ScrapeDirectories + { + BaseSaveDirectory = "Base Save Directory Not Relevant Here", + Id = 1, + BaseDirectory = "Base Directory Not Relevant Here", + SubDirectoryName = "Sub Directory Not Relevant Here", + BaseDirectoryFamous = "Base Directory Famous Not Relevant Here", + RootDirectory = "Root Directory Not Relevant Here" + } + .ToJson() + .ShouldMatchApproved(); +} \ No newline at end of file diff --git a/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/Models/SearchCategoryShould.ContainTheExpectedProperties.approved.txt b/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/Models/SearchCategoryShould.ContainTheExpectedProperties.approved.txt new file mode 100644 index 0000000..b898cc1 --- /dev/null +++ b/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/Models/SearchCategoryShould.ContainTheExpectedProperties.approved.txt @@ -0,0 +1,8 @@ +{ + "id": "1", + "order": 3, + "name": "Name Not Relevant Here", + "lastKnownImageCount": 1, + "lastPageVisited": 2, + "totalPages": 4 +} \ No newline at end of file diff --git a/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/Models/SearchCategoryShould.cs b/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/Models/SearchCategoryShould.cs new file mode 100644 index 0000000..6f60312 --- /dev/null +++ b/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/Models/SearchCategoryShould.cs @@ -0,0 +1,20 @@ +using AStar.Dev.Utilities; +using JetBrains.Annotations; + +namespace AStar.Dev.Admin.Api.Client.Sdk.Models; + +[TestSubject(typeof(SearchCategory))] +public class SearchCategoryShould +{ + [Fact] + public void ContainTheExpectedProperties() + => new SearchCategory + { + Id = "1", + Name = "Name Not Relevant Here", + LastKnownImageCount = 1, + LastPageVisited = 2, + Order = 3, + TotalPages = 4 + }.ToJson().ShouldMatchApproved(); +} \ No newline at end of file diff --git a/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/Models/SearchConfigurationShould.ContainTheExpectedProperties.approved.txt b/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/Models/SearchConfigurationShould.ContainTheExpectedProperties.approved.txt new file mode 100644 index 0000000..a41daa3 --- /dev/null +++ b/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/Models/SearchConfigurationShould.ContainTheExpectedProperties.approved.txt @@ -0,0 +1,28 @@ +{ + "id": 1, + "baseUrl": "https://not.relevant.here", + "loginUrl": "/not/relevant/here", + "searchCategories": [ + { + "id": "111", + "order": 2, + "name": "Name NotRelevant Here", + "lastKnownImageCount": 8, + "lastPageVisited": 9, + "totalPages": 7 + } + ], + "searchString": "", + "topWallpapers": "", + "searchStringPrefix": "", + "searchStringSuffix": "", + "subscriptions": "", + "imagePauseInSeconds": 5, + "startingPageNumber": 0, + "totalPages": 9, + "useHeadless": false, + "subscriptionsStartingPageNumber": 0, + "subscriptionsTotalPages": 0, + "topWallpapersTotalPages": 0, + "topWallpapersStartingPageNumber": 0 +} \ No newline at end of file diff --git a/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/Models/SearchConfigurationShould.cs b/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/Models/SearchConfigurationShould.cs new file mode 100644 index 0000000..7113966 --- /dev/null +++ b/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/Models/SearchConfigurationShould.cs @@ -0,0 +1,33 @@ +using AStar.Dev.Utilities; +using JetBrains.Annotations; + +namespace AStar.Dev.Admin.Api.Client.Sdk.Models; + +[TestSubject(typeof(SearchConfiguration))] +public class SearchConfigurationShould +{ + [Fact] + public void ContainTheExpectedProperties() + => new SearchConfiguration + { + BaseUrl = "https://not.relevant.here", + TotalPages = 9, + Id = 1, + ImagePauseInSeconds = 5, + LoginUrl = "/not/relevant/here", + SearchCategories = + [ + new() + { + Id = "111", + TotalPages = 7, + LastKnownImageCount = 8, + LastPageVisited = 9, + Name = "Name NotRelevant Here", + Order = 2 + } + ] + } + .ToJson() + .ShouldMatchApproved(); +} \ No newline at end of file diff --git a/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/Models/SiteConfigurationShould.ContainTheExpectedProperties.approved.txt b/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/Models/SiteConfigurationShould.ContainTheExpectedProperties.approved.txt new file mode 100644 index 0000000..c561002 --- /dev/null +++ b/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/Models/SiteConfigurationShould.ContainTheExpectedProperties.approved.txt @@ -0,0 +1,9 @@ +{ + "id": 1, + "loginEmailAddress": "not@relevant.com", + "username": "username not relevant here", + "password": "Nope, not this!", + "siteConfigurationSlug": "slug-not-relevant-here", + "baseUrl": "https://not.relevant.here", + "loginUrl": "/login/not/relevant/here" +} \ No newline at end of file diff --git a/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/Models/SiteConfigurationShould.cs b/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/Models/SiteConfigurationShould.cs new file mode 100644 index 0000000..34c7d81 --- /dev/null +++ b/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/Models/SiteConfigurationShould.cs @@ -0,0 +1,23 @@ +using AStar.Dev.Utilities; +using JetBrains.Annotations; + +namespace AStar.Dev.Admin.Api.Client.Sdk.Models; + +[TestSubject(typeof(SiteConfiguration))] +public class SiteConfigurationShould +{ + [Fact] + public void ContainTheExpectedProperties() + => new SiteConfiguration + { + BaseUrl = "https://not.relevant.here", + Id = 1, + LoginUrl = "/login/not/relevant/here", + LoginEmailAddress = "not@relevant.com", + Password = "Nope, not this!", + SiteConfigurationSlug = "slug-not-relevant-here", + Username = "username not relevant here" + } + .ToJson() + .ShouldMatchApproved(); +} \ No newline at end of file diff --git a/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/Models/TagToIgnoreShould.ContainTheExpectedProperties.approved.txt b/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/Models/TagToIgnoreShould.ContainTheExpectedProperties.approved.txt new file mode 100644 index 0000000..17d8671 --- /dev/null +++ b/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/Models/TagToIgnoreShould.ContainTheExpectedProperties.approved.txt @@ -0,0 +1,4 @@ +{ + "value": "Value not relevant here", + "ignoreImage": true +} \ No newline at end of file diff --git a/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/Models/TagToIgnoreShould.cs b/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/Models/TagToIgnoreShould.cs new file mode 100644 index 0000000..3c61a75 --- /dev/null +++ b/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/Models/TagToIgnoreShould.cs @@ -0,0 +1,12 @@ +using AStar.Dev.Utilities; +using JetBrains.Annotations; + +namespace AStar.Dev.Admin.Api.Client.Sdk.Models; + +[TestSubject(typeof(TagToIgnore))] +public class TagToIgnoreShould +{ + [Fact] + public void ContainTheExpectedProperties() + => new TagToIgnore { Value = "Value not relevant here", IgnoreImage = true }.ToJson().ShouldMatchApproved(); +} \ No newline at end of file diff --git a/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/ServiceCollectionExtensionsShould.cs b/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/ServiceCollectionExtensionsShould.cs new file mode 100644 index 0000000..a529170 --- /dev/null +++ b/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/ServiceCollectionExtensionsShould.cs @@ -0,0 +1,44 @@ +using AStar.Dev.Admin.Api.Client.Sdk.AdminApi; +using AStar.Dev.Logging.Extensions; +using JetBrains.Annotations; +using Microsoft.ApplicationInsights.Channel; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.Extensions.Options; +using Microsoft.Identity.Web; +using NSubstitute; + +namespace AStar.Dev.Admin.Api.Client.Sdk; + +[TestSubject(typeof(ServiceCollectionExtensions))] +public class ServiceCollectionExtensionsShould +{ + private readonly ServiceProvider serviceProvider; + + public ServiceCollectionExtensionsShould() + { + var configurationManager = new ConfigurationManager(); + configurationManager.AddJsonFile("appsettings.json"); + var serviceCollection = new ServiceCollection(); + var tokenAcquisitionServiceMock = Substitute.For(); + serviceCollection.AddSingleton(tokenAcquisitionServiceMock); + var loggerMock = Substitute.For>(); + serviceCollection.AddSingleton(loggerMock); + + serviceCollection.AddAdminApiClient(configurationManager); + + serviceProvider = serviceCollection.BuildServiceProvider(); + } + [Fact] + public void AddTheExpectedServices() + { + serviceProvider.GetService>().ShouldNotBeNull(); + serviceProvider.GetService().ShouldNotBeNull(); + } + + [Fact] + public void AddTheExpectedHttpClient() + => serviceProvider.GetService().ShouldNotBeNull(); +} \ No newline at end of file diff --git a/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/appsettings.json b/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/appsettings.json new file mode 100644 index 0000000..ba47ed0 --- /dev/null +++ b/test/AStar.Dev.Admin.Api.Client.Sdk.Tests.Unit/appsettings.json @@ -0,0 +1,74 @@ +{ + "DetailedErrors": true, + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "apiUsageConfiguration": { + "hostName": "astar-api-usage", + "userName": "user", + "password": null, + "queueName": "usage" + }, + "AllowedHosts": "*", + "AzureAd": { + "Instance": "https://login.microsoftonline.com/", + "Domain": "jasonbardenoutlook.onmicrosoft.com", + "TenantId": "bb7d94aa-36a9-4a59-a0c1-54a757c47ddf", + "ClientId": "2ca26585-5929-4aae-86a7-a00c3fc2d061", + "ClientSecret": "This is a secret... LOL", + "CallbackPath": "/signin-oidc" + }, + "TodoList": { + "Scopes": [ + "api://2ca26585-5929-4aae-86a7-a00c3fc2d061/ToDoList.Read", + "api://2ca26585-5929-4aae-86a7-a00c3fc2d061/ToDoList.Write" + ], + "BaseUrl": "http://todolistservice/", + "RelativePath": "api/todolist" + }, + "GraphApi": { + "BaseUrl": "https://graph.microsoft.com/v1.0/me", + "Scopes": [ + "user.read" + ] + }, + "apiConfiguration": { + "adminApiConfiguration": { + "Scopes": [ + "api://2ca26585-5929-4aae-86a7-a00c3fc2d061/ToDoList.Read", + "api://2ca26585-5929-4aae-86a7-a00c3fc2d061/ToDoList.Write" + ], + "baseUrl": "http://astar.dev.admin.api/" + }, + "filesApiConfiguration": { + "Scopes": [ + "api://54861ab2-fdb0-4e18-a073-c90e7bf9f0c5/ToDoList.Write", + "api://54861ab2-fdb0-4e18-a073-c90e7bf9f0c5/ToDoList.Read" + ], + "baseUrl": "http://astar.dev.files.api/" + }, + "imagesApiConfiguration": { + "Scopes": [ + "api://2ca26585-5929-4aae-86a7-a00c3fc2d061/ToDoList.Read", + "api://2ca26585-5929-4aae-86a7-a00c3fc2d061/ToDoList.Write" + ], + "baseUrl": "http://host.docker.internal:5062/" + }, + "usageApiConfiguration": { + "Scopes": [ + "api://2ca26585-5929-4aae-86a7-a00c3fc2d061/ToDoList.Read", + "api://2ca26585-5929-4aae-86a7-a00c3fc2d061/ToDoList.Write" + ], + "baseUrl": "http://astar.dev.usage.logger/" + } + }, + "applicationConfiguration": { + "paginationPageDefaultPreAndPostCount": 5 + }, + "ApplicationInsights": { + "ConnectionString": "InstrumentationKey=Update" + } +} diff --git a/test/unit/AStar.Dev.Example.ClassLib.Tests.Unit/AStar.Dev.Example.ClassLib.Tests.Unit.csproj b/test/unit/AStar.Dev.Example.ClassLib.Tests.Unit/AStar.Dev.Example.ClassLib.Tests.Unit.csproj deleted file mode 100644 index 6fbda4a..0000000 --- a/test/unit/AStar.Dev.Example.ClassLib.Tests.Unit/AStar.Dev.Example.ClassLib.Tests.Unit.csproj +++ /dev/null @@ -1,25 +0,0 @@ - - - - net9.0 - enable - enable - false - - - - - - - - - - - - - - - - - - diff --git a/test/unit/AStar.Dev.Example.ClassLib.Tests.Unit/UnitTest1.cs b/test/unit/AStar.Dev.Example.ClassLib.Tests.Unit/UnitTest1.cs deleted file mode 100644 index 3928e91..0000000 --- a/test/unit/AStar.Dev.Example.ClassLib.Tests.Unit/UnitTest1.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace AStar.Dev.Example.ClassLib.Tests.Unit; - -public class UnitTest1 -{ - [Fact] - public void Test1() - { - - } -}