diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index ea2c34b..ad52741 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -3,7 +3,7 @@ "isRoot": true, "tools": { "jetbrains.resharper.globaltools": { - "version": "2023.2.1", + "version": "2023.3.0-eap08", "commands": [ "jb" ] @@ -15,7 +15,7 @@ ] }, "dotnet-reportgenerator-globaltool": { - "version": "5.1.25", + "version": "5.2.0", "commands": [ "reportgenerator" ] diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index a45d71e..d204896 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -1,6 +1,6 @@ --- name: Bug report -about: Create a report to help us improve +about: Create a report to help us improve. title: '' labels: 'bug' assignees: '' diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..8bf0a91 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,14 @@ +blank_issues_enabled: true +contact_links: +- name: Documentation + url: https://www.jsonapi.net/usage/resources/index.html + about: Read our comprehensive documentation. +- name: Sponsor JsonApiDotNetCore + url: https://github.com/sponsors/json-api-dotnet + about: Help the continued development. +- name: Ask on Gitter + url: https://gitter.im/json-api-dotnet-core/Lobby + about: Get in touch with the whole community. +- name: Ask on Stack Overflow + url: https://stackoverflow.com/questions/tagged/json-api + about: The best place for asking general-purpose questions. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index f629ca4..019f7a9 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -1,6 +1,6 @@ --- name: Feature request -about: Suggest an idea for this project +about: Suggest an idea for this project. title: '' labels: 'enhancement' assignees: '' diff --git a/.github/ISSUE_TEMPLATE/question.md b/.github/ISSUE_TEMPLATE/question.md index 76b3998..2520ad8 100644 --- a/.github/ISSUE_TEMPLATE/question.md +++ b/.github/ISSUE_TEMPLATE/question.md @@ -1,6 +1,6 @@ --- name: Question -about: Ask a question +about: Ask a question. title: '' labels: 'question' assignees: '' diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index dc41703..881e2ed 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -38,7 +38,9 @@ jobs: - name: Setup .NET uses: actions/setup-dotnet@v3 with: - dotnet-version: 6.0.x + dotnet-version: | + 6.0.x + 8.0.x - name: Setup PowerShell (Ubuntu) if: matrix.os == 'ubuntu-latest' run: | @@ -118,10 +120,13 @@ jobs: dotnet build --no-restore --configuration Release /p:VersionSuffix=$env:PACKAGE_VERSION_SUFFIX - name: Test run: | - dotnet test --no-build --configuration Release --collect:"XPlat Code Coverage" --logger "GitHubActions;summary.includeSkippedTests=true" -- RunConfiguration.CollectSourceInformation=true DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.DeterministicReport=true + dotnet test --no-build --configuration Release --collect:"XPlat Code Coverage" --logger "GitHubActions;summary.includeSkippedTests=true" - name: Upload coverage to codecov.io if: matrix.os == 'ubuntu-latest' uses: codecov/codecov-action@v3 + with: + fail_ci_if_error: true + verbose: true - name: Generate packages shell: pwsh run: | @@ -146,7 +151,9 @@ jobs: - name: Setup .NET uses: actions/setup-dotnet@v3 with: - dotnet-version: 6.0.x + dotnet-version: | + 6.0.x + 8.0.x - name: Git checkout uses: actions/checkout@v4 - name: Restore tools @@ -157,7 +164,7 @@ jobs: run: | $inspectCodeOutputPath = Join-Path $env:RUNNER_TEMP 'jetbrains-inspectcode-results.xml' Write-Output "INSPECT_CODE_OUTPUT_PATH=$inspectCodeOutputPath" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append - dotnet jb inspectcode JsonApiDotNetCore.MongoDb.sln --build --output="$inspectCodeOutputPath" --profile=WarningSeverities.DotSettings --properties:Configuration=Release --properties:ContinuousIntegrationBuild=false --severity=WARNING --verbosity=WARN -dsl=GlobalAll -dsl=GlobalPerProduct -dsl=SolutionPersonal -dsl=ProjectPersonal + dotnet jb inspectcode JsonApiDotNetCore.MongoDb.sln --build --dotnetcoresdk=$(dotnet --version) --output="$inspectCodeOutputPath" --profile=WarningSeverities.DotSettings --properties:Configuration=Release --properties:ContinuousIntegrationBuild=false --severity=WARNING --verbosity=WARN -dsl=GlobalAll -dsl=GlobalPerProduct -dsl=SolutionPersonal -dsl=ProjectPersonal - name: Verify outcome shell: pwsh run: | @@ -197,7 +204,9 @@ jobs: - name: Setup .NET uses: actions/setup-dotnet@v3 with: - dotnet-version: 6.0.x + dotnet-version: | + 6.0.x + 8.0.x - name: Git checkout uses: actions/checkout@v4 with: @@ -218,13 +227,13 @@ jobs: $baseCommitHash = git rev-parse HEAD~1 Write-Output "Running code cleanup on commit range $baseCommitHash..$headCommitHash in pull request." - dotnet regitlint -s JsonApiDotNetCore.MongoDb.sln --print-command --skip-tool-check --max-runs=5 --jb-profile="JADNC Full Cleanup" --jb --properties:Configuration=Release --jb --verbosity=WARN -f commits -a $headCommitHash -b $baseCommitHash --fail-on-diff --print-diff + dotnet regitlint -s JsonApiDotNetCore.MongoDb.sln --print-command --skip-tool-check --max-runs=5 --jb --dotnetcoresdk=$(dotnet --version) --jb-profile="JADNC Full Cleanup" --jb --properties:Configuration=Release --jb --verbosity=WARN -f commits -a $headCommitHash -b $baseCommitHash --fail-on-diff --print-diff - name: CleanupCode (on branch) if: github.event_name == 'push' || github.event_name == 'release' shell: pwsh run: | Write-Output "Running code cleanup on all files." - dotnet regitlint -s JsonApiDotNetCore.MongoDb.sln --print-command --skip-tool-check --jb-profile="JADNC Full Cleanup" --jb --properties:Configuration=Release --jb --verbosity=WARN --fail-on-diff --print-diff + dotnet regitlint -s JsonApiDotNetCore.MongoDb.sln --print-command --skip-tool-check --jb --dotnetcoresdk=$(dotnet --version) --jb-profile="JADNC Full Cleanup" --jb --properties:Configuration=Release --jb --verbosity=WARN --fail-on-diff --print-diff publish: timeout-minutes: 60 diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 0000000..5b1868e --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,43 @@ +name: "CodeQL" + +on: + push: + branches: [ 'master', 'release/**' ] + pull_request: + # The branches below must be a subset of the branches above + branches: [ 'master', 'release/**' ] + schedule: + - cron: '0 0 * * 5' + +jobs: + analyze: + name: Analyze + runs-on: 'ubuntu-latest' + timeout-minutes: 60 + permissions: + actions: read + contents: read + security-events: write + strategy: + fail-fast: false + matrix: + language: [ 'csharp' ] + steps: + - name: Setup .NET + uses: actions/setup-dotnet@v3 + with: + dotnet-version: | + 6.0.x + 8.0.x + - name: Git checkout + uses: actions/checkout@v4 + - name: Initialize CodeQL + uses: github/codeql-action/init@v2 + with: + languages: ${{ matrix.language }} + - name: Autobuild + uses: github/codeql-action/autobuild@v2 + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v2 + with: + category: "/language:${{matrix.language}}" diff --git a/.github/workflows/deps-review.yml b/.github/workflows/deps-review.yml new file mode 100644 index 0000000..b994508 --- /dev/null +++ b/.github/workflows/deps-review.yml @@ -0,0 +1,14 @@ +name: 'Dependency Review' +on: [pull_request] + +permissions: + contents: read + +jobs: + dependency-review: + runs-on: ubuntu-latest + steps: + - name: 'Checkout Repository' + uses: actions/checkout@v4 + - name: 'Dependency Review' + uses: actions/dependency-review-action@v3 diff --git a/Build.ps1 b/Build.ps1 index 4854651..3abc926 100644 --- a/Build.ps1 +++ b/Build.ps1 @@ -10,13 +10,16 @@ Write-Host "$(pwsh --version)" Write-Host "Active .NET SDK: $(dotnet --version)" Write-Host "Using version suffix: $versionSuffix" +Remove-Item -Recurse -Force artifacts -ErrorAction SilentlyContinue +Remove-Item -Recurse -Force * -Include coverage.cobertura.xml + dotnet tool restore VerifySuccessExitCode dotnet build --configuration Release /p:VersionSuffix=$versionSuffix VerifySuccessExitCode -dotnet test --no-build --configuration Release --collect:"XPlat Code Coverage" -- DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.DeterministicReport=true +dotnet test --no-build --configuration Release --collect:"XPlat Code Coverage" VerifySuccessExitCode dotnet reportgenerator -reports:**\coverage.cobertura.xml -targetdir:artifacts\coverage -filefilters:-*.g.cs diff --git a/Directory.Build.props b/Directory.Build.props index c2e8807..dbaf920 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,9 +1,9 @@ - + $(NoWarn);AV2210 - + $(NoWarn);1591 true true @@ -13,42 +13,20 @@ true - - - net6.0 - 5.4.0 - 2.20.0 - - 4.1.0 - - - 6.0.* - 34.0.* - 3.8.* - 6.0.* - 1.1.* - 6.12.* - 2.3.* - 1.3.* - 2023.2.* - 2.21.* - 1.1.* - 17.7.* - 2.5.* - - - - + + enable + latest enable false false $(MSBuildThisFileDirectory)CodingGuidelines.ruleset - 5.4.0 + $(MSBuildThisFileDirectory)tests.runsettings + 5.5.0 diff --git a/JsonApiDotNetCore.MongoDb.sln b/JsonApiDotNetCore.MongoDb.sln index 0f6c7b7..81b5b78 100644 --- a/JsonApiDotNetCore.MongoDb.sln +++ b/JsonApiDotNetCore.MongoDb.sln @@ -26,6 +26,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution CodingGuidelines.ruleset = CodingGuidelines.ruleset CSharpGuidelinesAnalyzer.config = CSharpGuidelinesAnalyzer.config Directory.Build.props = Directory.Build.props + tests.runsettings = tests.runsettings + package-versions.props = package-versions.props EndProjectSection EndProject Global diff --git a/JsonApiDotNetCore.MongoDb.sln.DotSettings b/JsonApiDotNetCore.MongoDb.sln.DotSettings index 8e89021..d7699ea 100644 --- a/JsonApiDotNetCore.MongoDb.sln.DotSettings +++ b/JsonApiDotNetCore.MongoDb.sln.DotSettings @@ -66,6 +66,7 @@ JsonApiDotNetCore.MongoDb.ArgumentGuard.NotNull($EXPR$); WARNING WARNING WARNING + SUGGESTION SUGGESTION SUGGESTION DO_NOT_SHOW @@ -92,7 +93,9 @@ JsonApiDotNetCore.MongoDb.ArgumentGuard.NotNull($EXPR$); WARNING SUGGESTION SUGGESTION + SUGGESTION WARNING + SUGGESTION <?xml version="1.0" encoding="utf-16"?><Profile name="JADNC Full Cleanup"><XMLReformatCode>True</XMLReformatCode><CSCodeStyleAttributes ArrangeTypeAccessModifier="True" ArrangeTypeMemberAccessModifier="True" SortModifiers="True" RemoveRedundantParentheses="True" AddMissingParentheses="True" ArrangeBraces="True" ArrangeAttributes="True" ArrangeArgumentsStyle="True" ArrangeCodeBodyStyle="True" ArrangeVarStyle="True" ArrangeTrailingCommas="True" ArrangeObjectCreation="True" ArrangeDefaultValue="True" ArrangeNamespaces="True" ArrangeNullCheckingPattern="True" /><CssAlphabetizeProperties>True</CssAlphabetizeProperties><JsInsertSemicolon>True</JsInsertSemicolon><FormatAttributeQuoteDescriptor>True</FormatAttributeQuoteDescriptor><CorrectVariableKindsDescriptor>True</CorrectVariableKindsDescriptor><VariablesToInnerScopesDescriptor>True</VariablesToInnerScopesDescriptor><StringToTemplatesDescriptor>True</StringToTemplatesDescriptor><JsReformatCode>True</JsReformatCode><JsFormatDocComments>True</JsFormatDocComments><RemoveRedundantQualifiersTs>True</RemoveRedundantQualifiersTs><OptimizeImportsTs>True</OptimizeImportsTs><OptimizeReferenceCommentsTs>True</OptimizeReferenceCommentsTs><PublicModifierStyleTs>True</PublicModifierStyleTs><ExplicitAnyTs>True</ExplicitAnyTs><TypeAnnotationStyleTs>True</TypeAnnotationStyleTs><RelativePathStyleTs>True</RelativePathStyleTs><AsInsteadOfCastTs>True</AsInsteadOfCastTs><HtmlReformatCode>True</HtmlReformatCode><AspOptimizeRegisterDirectives>True</AspOptimizeRegisterDirectives><RemoveCodeRedundancies>True</RemoveCodeRedundancies><CSUseAutoProperty>True</CSUseAutoProperty><CSMakeFieldReadonly>True</CSMakeFieldReadonly><CSMakeAutoPropertyGetOnly>True</CSMakeAutoPropertyGetOnly><CSArrangeQualifiers>True</CSArrangeQualifiers><CSFixBuiltinTypeReferences>True</CSFixBuiltinTypeReferences><CssReformatCode>True</CssReformatCode><CSOptimizeUsings><OptimizeUsings>True</OptimizeUsings></CSOptimizeUsings><CSShortenReferences>True</CSShortenReferences><CSReformatCode>True</CSReformatCode><CSharpFormatDocComments>True</CSharpFormatDocComments><CSReorderTypeMembers>True</CSReorderTypeMembers><XAMLCollapseEmptyTags>False</XAMLCollapseEmptyTags><CSReformatInactiveBranches>True</CSReformatInactiveBranches></Profile> JADNC Full Cleanup Required @@ -113,6 +116,7 @@ JsonApiDotNetCore.MongoDb.ArgumentGuard.NotNull($EXPR$); True True True + INDENT 1 1 False @@ -125,6 +129,7 @@ JsonApiDotNetCore.MongoDb.ArgumentGuard.NotNull($EXPR$); False False True + 1 NEVER NEVER False @@ -145,6 +150,7 @@ JsonApiDotNetCore.MongoDb.ArgumentGuard.NotNull($EXPR$); True WRAP_IF_LONG 160 + CHOP_IF_LONG WRAP_IF_LONG CHOP_ALWAYS CHOP_ALWAYS diff --git a/WarningSeverities.DotSettings b/WarningSeverities.DotSettings index 96f358d..5c641e6 100644 --- a/WarningSeverities.DotSettings +++ b/WarningSeverities.DotSettings @@ -124,6 +124,7 @@ WARNING WARNING WARNING + WARNING WARNING WARNING WARNING @@ -163,6 +164,7 @@ WARNING WARNING WARNING + WARNING WARNING WARNING WARNING @@ -240,6 +242,7 @@ WARNING WARNING WARNING + WARNING WARNING WARNING WARNING @@ -258,10 +261,12 @@ WARNING WARNING WARNING + WARNING WARNING WARNING WARNING WARNING WARNING WARNING + WARNING \ No newline at end of file diff --git a/cleanupcode.ps1 b/cleanupcode.ps1 index 23f2a36..a593bd9 100644 --- a/cleanupcode.ps1 +++ b/cleanupcode.ps1 @@ -28,17 +28,17 @@ if ($revision) { if ($baseCommitHash -eq $headCommitHash) { Write-Output "Running code cleanup on staged/unstaged files." - dotnet regitlint -s JsonApiDotNetCore.MongoDb.sln --print-command --skip-tool-check --max-runs=5 --jb-profile="JADNC Full Cleanup" --jb --properties:Configuration=Release --jb --verbosity=WARN -f staged,modified + dotnet regitlint -s JsonApiDotNetCore.MongoDb.sln --print-command --skip-tool-check --max-runs=5 --jb --dotnetcoresdk=$(dotnet --version) --jb-profile="JADNC Full Cleanup" --jb --properties:Configuration=Release --jb --verbosity=WARN -f staged,modified VerifySuccessExitCode } else { Write-Output "Running code cleanup on commit range $baseCommitHash..$headCommitHash, including staged/unstaged files." - dotnet regitlint -s JsonApiDotNetCore.MongoDb.sln --print-command --skip-tool-check --max-runs=5 --jb-profile="JADNC Full Cleanup" --jb --properties:Configuration=Release --jb --verbosity=WARN -f staged,modified,commits -a $headCommitHash -b $baseCommitHash + dotnet regitlint -s JsonApiDotNetCore.MongoDb.sln --print-command --skip-tool-check --max-runs=5 --jb --dotnetcoresdk=$(dotnet --version) --jb-profile="JADNC Full Cleanup" --jb --properties:Configuration=Release --jb --verbosity=WARN -f staged,modified,commits -a $headCommitHash -b $baseCommitHash VerifySuccessExitCode } } else { Write-Output "Running code cleanup on all files." - dotnet regitlint -s JsonApiDotNetCore.MongoDb.sln --print-command --skip-tool-check --jb-profile="JADNC Full Cleanup" --jb --properties:Configuration=Release --jb --verbosity=WARN + dotnet regitlint -s JsonApiDotNetCore.MongoDb.sln --print-command --skip-tool-check --jb --dotnetcoresdk=$(dotnet --version) --jb-profile="JADNC Full Cleanup" --jb --properties:Configuration=Release --jb --verbosity=WARN VerifySuccessExitCode } diff --git a/inspectcode.ps1 b/inspectcode.ps1 index dc81b09..13f0abb 100644 --- a/inspectcode.ps1 +++ b/inspectcode.ps1 @@ -10,7 +10,7 @@ if ($LastExitCode -ne 0) { $outputPath = [System.IO.Path]::Combine([System.IO.Path]::GetTempPath(), 'jetbrains-inspectcode-results.xml') $resultPath = [System.IO.Path]::Combine([System.IO.Path]::GetTempPath(), 'jetbrains-inspectcode-results.html') -dotnet jb inspectcode JsonApiDotNetCore.MongoDb.sln --build --output="$outputPath" --profile=WarningSeverities.DotSettings --properties:Configuration=Release --severity=WARNING --verbosity=WARN -dsl=GlobalAll -dsl=GlobalPerProduct -dsl=SolutionPersonal -dsl=ProjectPersonal +dotnet jb inspectcode JsonApiDotNetCore.MongoDb.sln --dotnetcoresdk=$(dotnet --version) --build --output="$outputPath" --profile=WarningSeverities.DotSettings --properties:Configuration=Release --severity=WARNING --verbosity=WARN -dsl=GlobalAll -dsl=GlobalPerProduct -dsl=SolutionPersonal -dsl=ProjectPersonal if ($LastExitCode -ne 0) { throw "Code inspection failed with exit code $LastExitCode" diff --git a/package-versions.props b/package-versions.props new file mode 100644 index 0000000..6d226f5 --- /dev/null +++ b/package-versions.props @@ -0,0 +1,29 @@ + + + + 5.5.0 + 2.20.0 + + + 34.0.* + 6.0.* + 1.1.* + 6.12.* + 2.3.* + 1.3.* + 2.22.* + 8.0.* + 17.8.* + 2.5.* + + + + + 8.0.* + + + + + 6.0.* + + diff --git a/run-docker-mongodb.ps1 b/run-docker-mongodb.ps1 index b1092b4..215b048 100644 --- a/run-docker-mongodb.ps1 +++ b/run-docker-mongodb.ps1 @@ -1,9 +1,6 @@ #Requires -Version 7.0 -# This script starts a docker container with MongoDB database, used for running tests. +# This script starts a MongoDB database in a docker container, which is required for running examples locally. -docker container stop jsonapi-dotnet-core-mongodb-testing - -docker run --rm --name jsonapi-dotnet-core-mongodb-testing ` - -p 27017:27017 ` - mongo:latest +docker container stop jsonapi-mongo-db +docker run --pull always --rm --detach --name jsonapi-mongo-db -p 27017:27017 mongo:latest diff --git a/src/Examples/GettingStarted/GettingStarted.csproj b/src/Examples/GettingStarted/GettingStarted.csproj index a5b25ea..0f6b40f 100644 --- a/src/Examples/GettingStarted/GettingStarted.csproj +++ b/src/Examples/GettingStarted/GettingStarted.csproj @@ -1,8 +1,10 @@ - $(TargetFrameworkName) + net8.0;net6.0 + + diff --git a/src/Examples/GettingStarted/Program.cs b/src/Examples/GettingStarted/Program.cs index e28c933..7deafcc 100644 --- a/src/Examples/GettingStarted/Program.cs +++ b/src/Examples/GettingStarted/Program.cs @@ -2,23 +2,20 @@ using JsonApiDotNetCore.Configuration; using JsonApiDotNetCore.MongoDb.Configuration; using JsonApiDotNetCore.MongoDb.Repositories; +using Microsoft.Extensions.DependencyInjection.Extensions; using MongoDB.Driver; WebApplicationBuilder builder = WebApplication.CreateBuilder(args); // Add services to the container. -builder.Services.AddSingleton(_ => +builder.Services.TryAddSingleton(_ => { var client = new MongoClient(builder.Configuration.GetSection("DatabaseSettings:ConnectionString").Value); return client.GetDatabase(builder.Configuration.GetSection("DatabaseSettings:Database").Value); }); -builder.Services.AddJsonApi(ConfigureJsonApiOptions, resources: resourceGraphBuilder => -{ - resourceGraphBuilder.Add(); -}); - +builder.Services.AddJsonApi(ConfigureJsonApiOptions, resources: resourceGraphBuilder => resourceGraphBuilder.Add()); builder.Services.AddJsonApiMongoDb(); builder.Services.AddResourceRepository>(); diff --git a/src/Examples/JsonApiDotNetCoreMongoDbExample/Definitions/TodoItemDefinition.cs b/src/Examples/JsonApiDotNetCoreMongoDbExample/Definitions/TodoItemDefinition.cs index 61027b4..970a061 100644 --- a/src/Examples/JsonApiDotNetCoreMongoDbExample/Definitions/TodoItemDefinition.cs +++ b/src/Examples/JsonApiDotNetCoreMongoDbExample/Definitions/TodoItemDefinition.cs @@ -5,20 +5,30 @@ using JsonApiDotNetCore.Queries.Expressions; using JsonApiDotNetCore.Resources; using JsonApiDotNetCoreMongoDbExample.Models; +#if NET6_0 using Microsoft.AspNetCore.Authentication; +#endif namespace JsonApiDotNetCoreMongoDbExample.Definitions; [UsedImplicitly(ImplicitUseKindFlags.InstantiatedNoFixedConstructorSignature)] public sealed class TodoItemDefinition : JsonApiResourceDefinition { - private readonly ISystemClock _systemClock; + private readonly Func _getUtcNow; +#if NET6_0 public TodoItemDefinition(IResourceGraph resourceGraph, ISystemClock systemClock) : base(resourceGraph) { - _systemClock = systemClock; + _getUtcNow = () => systemClock.UtcNow; } +#else + public TodoItemDefinition(IResourceGraph resourceGraph, TimeProvider timeProvider) + : base(resourceGraph) + { + _getUtcNow = timeProvider.GetUtcNow; + } +#endif public override SortExpression OnApplySort(SortExpression? existingSort) { @@ -27,22 +37,21 @@ public override SortExpression OnApplySort(SortExpression? existingSort) private SortExpression GetDefaultSortOrder() { - return CreateSortExpressionFromLambda(new PropertySortOrder - { + return CreateSortExpressionFromLambda([ (todoItem => todoItem.Priority, ListSortDirection.Ascending), (todoItem => todoItem.LastModifiedAt, ListSortDirection.Descending) - }); + ]); } public override Task OnWritingAsync(TodoItem resource, WriteOperationKind writeOperation, CancellationToken cancellationToken) { if (writeOperation == WriteOperationKind.CreateResource) { - resource.CreatedAt = _systemClock.UtcNow; + resource.CreatedAt = _getUtcNow(); } else if (writeOperation == WriteOperationKind.UpdateResource) { - resource.LastModifiedAt = _systemClock.UtcNow; + resource.LastModifiedAt = _getUtcNow(); } return Task.CompletedTask; diff --git a/src/Examples/JsonApiDotNetCoreMongoDbExample/JsonApiDotNetCoreMongoDbExample.csproj b/src/Examples/JsonApiDotNetCoreMongoDbExample/JsonApiDotNetCoreMongoDbExample.csproj index a5b25ea..0f6b40f 100644 --- a/src/Examples/JsonApiDotNetCoreMongoDbExample/JsonApiDotNetCoreMongoDbExample.csproj +++ b/src/Examples/JsonApiDotNetCoreMongoDbExample/JsonApiDotNetCoreMongoDbExample.csproj @@ -1,8 +1,10 @@ - $(TargetFrameworkName) + net8.0;net6.0 + + diff --git a/src/Examples/JsonApiDotNetCoreMongoDbExample/Program.cs b/src/Examples/JsonApiDotNetCoreMongoDbExample/Program.cs index 9820cb1..95ec278 100644 --- a/src/Examples/JsonApiDotNetCoreMongoDbExample/Program.cs +++ b/src/Examples/JsonApiDotNetCoreMongoDbExample/Program.cs @@ -4,8 +4,11 @@ using JsonApiDotNetCore.MongoDb.Configuration; using JsonApiDotNetCore.MongoDb.Repositories; using JsonApiDotNetCore.Repositories; -using Microsoft.AspNetCore.Authentication; +using Microsoft.Extensions.DependencyInjection.Extensions; using MongoDB.Driver; +#if NET6_0 +using Microsoft.AspNetCore.Authentication; +#endif [assembly: ExcludeFromCodeCoverage] @@ -13,21 +16,25 @@ // Add services to the container. -builder.Services.AddSingleton(); +#if NET6_0 +builder.Services.TryAddSingleton(); +#else +builder.Services.TryAddSingleton(TimeProvider.System); +#endif -builder.Services.AddSingleton(_ => +builder.Services.TryAddSingleton(_ => { - var client = new MongoClient(builder.Configuration.GetSection("DatabaseSettings:ConnectionString").Value); - return client.GetDatabase(builder.Configuration.GetSection("DatabaseSettings:Database").Value); + var client = new MongoClient(builder.Configuration.GetValue("DatabaseSettings:ConnectionString")); + return client.GetDatabase(builder.Configuration.GetValue("DatabaseSettings:Database")); }); +builder.Services.TryAddScoped(typeof(IResourceReadRepository<,>), typeof(MongoRepository<,>)); +builder.Services.TryAddScoped(typeof(IResourceWriteRepository<,>), typeof(MongoRepository<,>)); +builder.Services.TryAddScoped(typeof(IResourceRepository<,>), typeof(MongoRepository<,>)); + builder.Services.AddJsonApi(ConfigureJsonApiOptions, facade => facade.AddCurrentAssembly()); builder.Services.AddJsonApiMongoDb(); -builder.Services.AddScoped(typeof(IResourceReadRepository<,>), typeof(MongoRepository<,>)); -builder.Services.AddScoped(typeof(IResourceWriteRepository<,>), typeof(MongoRepository<,>)); -builder.Services.AddScoped(typeof(IResourceRepository<,>), typeof(MongoRepository<,>)); - WebApplication app = builder.Build(); // Configure the HTTP request pipeline. diff --git a/src/JsonApiDotNetCore.MongoDb/AtomicOperations/MongoTransaction.cs b/src/JsonApiDotNetCore.MongoDb/AtomicOperations/MongoTransaction.cs index 3514e87..3ea882d 100644 --- a/src/JsonApiDotNetCore.MongoDb/AtomicOperations/MongoTransaction.cs +++ b/src/JsonApiDotNetCore.MongoDb/AtomicOperations/MongoTransaction.cs @@ -35,20 +35,24 @@ public Task AfterProcessOperationAsync(CancellationToken cancellationToken) } /// - public async Task CommitAsync(CancellationToken cancellationToken) + public Task CommitAsync(CancellationToken cancellationToken) { if (_ownsTransaction && _mongoDataAccess.ActiveSession != null) { - await _mongoDataAccess.ActiveSession.CommitTransactionAsync(cancellationToken); + return _mongoDataAccess.ActiveSession.CommitTransactionAsync(cancellationToken); } + + return Task.CompletedTask; } /// - public async ValueTask DisposeAsync() + public ValueTask DisposeAsync() { if (_ownsTransaction) { - await _mongoDataAccess.DisposeAsync(); + return _mongoDataAccess.DisposeAsync(); } + + return ValueTask.CompletedTask; } } diff --git a/src/JsonApiDotNetCore.MongoDb/Configuration/ServiceCollectionExtensions.cs b/src/JsonApiDotNetCore.MongoDb/Configuration/ServiceCollectionExtensions.cs index 836cf87..d39c8c7 100644 --- a/src/JsonApiDotNetCore.MongoDb/Configuration/ServiceCollectionExtensions.cs +++ b/src/JsonApiDotNetCore.MongoDb/Configuration/ServiceCollectionExtensions.cs @@ -5,6 +5,7 @@ using JsonApiDotNetCore.MongoDb.Repositories; using JsonApiDotNetCore.Queries; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; namespace JsonApiDotNetCore.MongoDb.Configuration; @@ -16,7 +17,9 @@ public static class ServiceCollectionExtensions [PublicAPI] public static IServiceCollection AddJsonApiMongoDb(this IServiceCollection services) { - services.AddScoped(); + services.TryAddScoped(); + + // Replace the built-in implementations from JsonApiDotNetCore. services.AddScoped(); services.AddScoped(); diff --git a/src/JsonApiDotNetCore.MongoDb/JsonApiDotNetCore.MongoDb.csproj b/src/JsonApiDotNetCore.MongoDb/JsonApiDotNetCore.MongoDb.csproj index 50df50f..07d7077 100644 --- a/src/JsonApiDotNetCore.MongoDb/JsonApiDotNetCore.MongoDb.csproj +++ b/src/JsonApiDotNetCore.MongoDb/JsonApiDotNetCore.MongoDb.csproj @@ -1,10 +1,12 @@ - $(TargetFrameworkName) + net8.0;net6.0 true true + + $(JsonApiDotNetCoreMongoDbVersionPrefix) jsonapi;json:api;dotnet;asp.net;rest;web-api;MongoDB diff --git a/src/JsonApiDotNetCore.MongoDb/Repositories/MongoRepository.cs b/src/JsonApiDotNetCore.MongoDb/Repositories/MongoRepository.cs index f983cef..c955f8c 100644 --- a/src/JsonApiDotNetCore.MongoDb/Repositories/MongoRepository.cs +++ b/src/JsonApiDotNetCore.MongoDb/Repositories/MongoRepository.cs @@ -173,12 +173,10 @@ public virtual async Task CreateAsync(TResource resourceFromRequest, TResource r await _resourceDefinitionAccessor.OnWritingAsync(resourceForDatabase, WriteOperationKind.CreateResource, cancellationToken); - await SaveChangesAsync(async () => - { - await (_mongoDataAccess.ActiveSession != null + await SaveChangesAsync( + () => _mongoDataAccess.ActiveSession != null ? Collection.InsertOneAsync(_mongoDataAccess.ActiveSession, resourceForDatabase, cancellationToken: cancellationToken) - : Collection.InsertOneAsync(resourceForDatabase, cancellationToken: cancellationToken)); - }, cancellationToken); + : Collection.InsertOneAsync(resourceForDatabase, cancellationToken: cancellationToken), cancellationToken); await _resourceDefinitionAccessor.OnWriteSucceededAsync(resourceForDatabase, WriteOperationKind.CreateResource, cancellationToken); } @@ -217,12 +215,10 @@ public virtual async Task UpdateAsync(TResource resourceFromRequest, TResource r FilterDefinition filter = Builders.Filter.Eq(resource => resource.Id, resourceFromDatabase.Id); - await SaveChangesAsync(async () => - { - await (_mongoDataAccess.ActiveSession != null + await SaveChangesAsync( + () => _mongoDataAccess.ActiveSession != null ? Collection.ReplaceOneAsync(_mongoDataAccess.ActiveSession, filter, resourceFromDatabase, cancellationToken: cancellationToken) - : Collection.ReplaceOneAsync(filter, resourceFromDatabase, cancellationToken: cancellationToken)); - }, cancellationToken); + : Collection.ReplaceOneAsync(filter, resourceFromDatabase, cancellationToken: cancellationToken), cancellationToken); await _resourceDefinitionAccessor.OnWriteSucceededAsync(resourceFromDatabase, WriteOperationKind.UpdateResource, cancellationToken); } @@ -238,9 +234,9 @@ public virtual async Task DeleteAsync(TResource? resourceFromDatabase, TId id, C FilterDefinition filter = Builders.Filter.Eq(resource => resource.Id, id); DeleteResult result = await SaveChangesAsync( - async () => _mongoDataAccess.ActiveSession != null - ? await Collection.DeleteOneAsync(_mongoDataAccess.ActiveSession, filter, cancellationToken: cancellationToken) - : await Collection.DeleteOneAsync(filter, cancellationToken), cancellationToken); + () => _mongoDataAccess.ActiveSession != null + ? Collection.DeleteOneAsync(_mongoDataAccess.ActiveSession, filter, cancellationToken: cancellationToken) + : Collection.DeleteOneAsync(filter, cancellationToken), cancellationToken); if (!result.IsAcknowledged) { diff --git a/src/JsonApiDotNetCore.MongoDb/Resources/IMongoIdentifiable.cs b/src/JsonApiDotNetCore.MongoDb/Resources/IMongoIdentifiable.cs index 11dbfa2..576cdcc 100644 --- a/src/JsonApiDotNetCore.MongoDb/Resources/IMongoIdentifiable.cs +++ b/src/JsonApiDotNetCore.MongoDb/Resources/IMongoIdentifiable.cs @@ -5,6 +5,4 @@ namespace JsonApiDotNetCore.MongoDb.Resources; /// /// Marker interface to indicate a resource that is stored in MongoDB. /// -public interface IMongoIdentifiable : IIdentifiable -{ -} +public interface IMongoIdentifiable : IIdentifiable; diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/AtomicOperationsFixture.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/AtomicOperationsFixture.cs index e727573..21db655 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/AtomicOperationsFixture.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/AtomicOperationsFixture.cs @@ -1,5 +1,7 @@ using JetBrains.Annotations; -using Microsoft.Extensions.DependencyInjection; +using JsonApiDotNetCore.Configuration; +using JsonApiDotNetCoreMongoDbTests.IntegrationTests.AtomicOperations.Meta; +using Microsoft.Extensions.DependencyInjection.Extensions; using TestBuildingBlocks; using Xunit; @@ -12,9 +14,17 @@ public sealed class AtomicOperationsFixture : IAsyncLifetime public AtomicOperationsFixture() { + TestContext.UseResourceTypesInNamespace(typeof(MusicTrack).Namespace); + TestContext.UseController(); - TestContext.ConfigureServicesAfterStartup(services => services.AddSingleton()); + TestContext.ConfigureServices(services => + { + services.TryAddSingleton(); + + services.AddResourceDefinition(); + services.AddResourceDefinition(); + }); } public Task InitializeAsync() @@ -22,8 +32,8 @@ public Task InitializeAsync() return Task.CompletedTask; } - public async Task DisposeAsync() + public Task DisposeAsync() { - await TestContext.DisposeAsync(); + return TestContext.DisposeAsync(); } } diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/BaseForAtomicOperationsTestsThatChangeOptions.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/BaseForAtomicOperationsTestsThatChangeOptions.cs index 9aa74e8..44397df 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/BaseForAtomicOperationsTestsThatChangeOptions.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/BaseForAtomicOperationsTestsThatChangeOptions.cs @@ -1,3 +1,4 @@ +using System.Reflection; using JsonApiDotNetCore.Configuration; using Microsoft.Extensions.DependencyInjection; @@ -20,66 +21,38 @@ public void Dispose() private sealed class JsonApiOptionsScope : IDisposable { + private static readonly List PropertyCache = typeof(JsonApiOptions).GetProperties().Where(IsAccessibleProperty).ToList(); + private readonly JsonApiOptions _options; private readonly JsonApiOptions _backupValues; - public JsonApiOptionsScope(IJsonApiOptions options) + public JsonApiOptionsScope(JsonApiOptions options) { - _options = (JsonApiOptions)options; + _options = options; + _backupValues = new JsonApiOptions(); - _backupValues = new JsonApiOptions - { - Namespace = options.Namespace, - DefaultAttrCapabilities = options.DefaultAttrCapabilities, - DefaultHasOneCapabilities = options.DefaultHasOneCapabilities, - DefaultHasManyCapabilities = options.DefaultHasManyCapabilities, - IncludeJsonApiVersion = options.IncludeJsonApiVersion, - IncludeExceptionStackTraceInErrors = options.IncludeExceptionStackTraceInErrors, - IncludeRequestBodyInErrors = options.IncludeRequestBodyInErrors, - UseRelativeLinks = options.UseRelativeLinks, - TopLevelLinks = options.TopLevelLinks, - ResourceLinks = options.ResourceLinks, - RelationshipLinks = options.RelationshipLinks, - IncludeTotalResourceCount = options.IncludeTotalResourceCount, - DefaultPageSize = options.DefaultPageSize, - MaximumPageSize = options.MaximumPageSize, - MaximumPageNumber = options.MaximumPageNumber, - ValidateModelState = options.ValidateModelState, - ClientIdGeneration = options.ClientIdGeneration, - AllowUnknownQueryStringParameters = options.AllowUnknownQueryStringParameters, - AllowUnknownFieldsInRequestBody = options.AllowUnknownFieldsInRequestBody, - EnableLegacyFilterNotation = options.EnableLegacyFilterNotation, - MaximumIncludeDepth = options.MaximumIncludeDepth, - MaximumOperationsPerRequest = options.MaximumOperationsPerRequest, - TransactionIsolationLevel = options.TransactionIsolationLevel - }; + CopyPropertyValues(_options, _backupValues); + } + + private static bool IsAccessibleProperty(PropertyInfo property) + { + return property.GetMethod != null && property.SetMethod != null && property.GetCustomAttribute() == null; } public void Dispose() { - _options.Namespace = _backupValues.Namespace; - _options.DefaultAttrCapabilities = _backupValues.DefaultAttrCapabilities; - _options.DefaultHasOneCapabilities = _backupValues.DefaultHasOneCapabilities; - _options.DefaultHasManyCapabilities = _backupValues.DefaultHasManyCapabilities; - _options.IncludeJsonApiVersion = _backupValues.IncludeJsonApiVersion; - _options.IncludeExceptionStackTraceInErrors = _backupValues.IncludeExceptionStackTraceInErrors; - _options.IncludeRequestBodyInErrors = _backupValues.IncludeRequestBodyInErrors; - _options.UseRelativeLinks = _backupValues.UseRelativeLinks; - _options.TopLevelLinks = _backupValues.TopLevelLinks; - _options.ResourceLinks = _backupValues.ResourceLinks; - _options.RelationshipLinks = _backupValues.RelationshipLinks; - _options.IncludeTotalResourceCount = _backupValues.IncludeTotalResourceCount; - _options.DefaultPageSize = _backupValues.DefaultPageSize; - _options.MaximumPageSize = _backupValues.MaximumPageSize; - _options.MaximumPageNumber = _backupValues.MaximumPageNumber; - _options.ValidateModelState = _backupValues.ValidateModelState; - _options.ClientIdGeneration = _backupValues.ClientIdGeneration; - _options.AllowUnknownQueryStringParameters = _backupValues.AllowUnknownQueryStringParameters; - _options.AllowUnknownFieldsInRequestBody = _backupValues.AllowUnknownFieldsInRequestBody; - _options.EnableLegacyFilterNotation = _backupValues.EnableLegacyFilterNotation; - _options.MaximumIncludeDepth = _backupValues.MaximumIncludeDepth; - _options.MaximumOperationsPerRequest = _backupValues.MaximumOperationsPerRequest; - _options.TransactionIsolationLevel = _backupValues.TransactionIsolationLevel; + CopyPropertyValues(_backupValues, _options); + } + + private static void CopyPropertyValues(JsonApiOptions source, JsonApiOptions destination) + { + foreach (PropertyInfo property in PropertyCache) + { + property.SetMethod!.Invoke(destination, new[] + { + property.GetMethod!.Invoke(source, null) + }); + } } } } diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Creating/AtomicCreateResourceWithClientGeneratedIdTests.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Creating/AtomicCreateResourceWithClientGeneratedIdTests.cs index bfd4a4e..27813bc 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Creating/AtomicCreateResourceWithClientGeneratedIdTests.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Creating/AtomicCreateResourceWithClientGeneratedIdTests.cs @@ -58,7 +58,7 @@ public async Task Can_create_resource_with_client_generated_string_ID_having_sid // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - string isoCode = $"{newLanguage.IsoCode}{ContainerTypeToHideFromAutoDiscovery.ImplicitlyChangingTextLanguageDefinition.Suffix}"; + string isoCode = $"{newLanguage.IsoCode}{ImplicitlyChangingTextLanguageDefinition.Suffix}"; responseDocument.Results.ShouldHaveCount(1); @@ -132,10 +132,10 @@ public async Task Cannot_create_resource_for_existing_client_generated_ID() string newIsoCode = _fakers.TextLanguage.Generate().IsoCode!; - await _testContext.RunOnDatabaseAsync(async dbContext => + await _testContext.RunOnDatabaseAsync(dbContext => { dbContext.TextLanguages.Add(existingLanguage); - await dbContext.SaveChangesAsync(); + return dbContext.SaveChangesAsync(); }); var requestBody = new diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Creating/AtomicCreateResourceWithToManyRelationshipTests.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Creating/AtomicCreateResourceWithToManyRelationshipTests.cs index 94eabe3..ad022d4 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Creating/AtomicCreateResourceWithToManyRelationshipTests.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Creating/AtomicCreateResourceWithToManyRelationshipTests.cs @@ -25,10 +25,10 @@ public async Task Cannot_create_ToMany_relationship() string newTitle = _fakers.MusicTrack.Generate().Title; - await _testContext.RunOnDatabaseAsync(async dbContext => + await _testContext.RunOnDatabaseAsync(dbContext => { dbContext.Performers.Add(existingPerformer); - await dbContext.SaveChangesAsync(); + return dbContext.SaveChangesAsync(); }); var requestBody = new diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Creating/AtomicCreateResourceWithToOneRelationshipTests.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Creating/AtomicCreateResourceWithToOneRelationshipTests.cs index dd7cf9e..209cdea 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Creating/AtomicCreateResourceWithToOneRelationshipTests.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Creating/AtomicCreateResourceWithToOneRelationshipTests.cs @@ -25,10 +25,10 @@ public async Task Cannot_create_ToOne_relationship() string newLyricText = _fakers.Lyric.Generate().Text; - await _testContext.RunOnDatabaseAsync(async dbContext => + await _testContext.RunOnDatabaseAsync(dbContext => { dbContext.MusicTracks.Add(existingTrack); - await dbContext.SaveChangesAsync(); + return dbContext.SaveChangesAsync(); }); var requestBody = new diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Deleting/AtomicDeleteResourceTests.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Deleting/AtomicDeleteResourceTests.cs index 5721c1b..14f62fb 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Deleting/AtomicDeleteResourceTests.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Deleting/AtomicDeleteResourceTests.cs @@ -23,10 +23,10 @@ public async Task Can_delete_existing_resource() // Arrange Performer existingPerformer = _fakers.Performer.Generate(); - await _testContext.RunOnDatabaseAsync(async dbContext => + await _testContext.RunOnDatabaseAsync(dbContext => { dbContext.Performers.Add(existingPerformer); - await dbContext.SaveChangesAsync(); + return dbContext.SaveChangesAsync(); }); var requestBody = new diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/ImplicitlyChangingTextLanguageDefinition.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/ImplicitlyChangingTextLanguageDefinition.cs index dc5ada1..946bc14 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/ImplicitlyChangingTextLanguageDefinition.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/ImplicitlyChangingTextLanguageDefinition.cs @@ -6,39 +6,34 @@ namespace JsonApiDotNetCoreMongoDbTests.IntegrationTests.AtomicOperations; -[UsedImplicitly] -public sealed class ContainerTypeToHideFromAutoDiscovery +/// +/// Used to simulate side effects that occur in the database while saving, typically caused by database triggers. +/// +[UsedImplicitly(ImplicitUseKindFlags.InstantiatedNoFixedConstructorSignature)] +public abstract class ImplicitlyChangingTextLanguageDefinition : HitCountingResourceDefinition { - /// - /// Used to simulate side effects that occur in the database while saving, typically caused by database triggers. - /// - [UsedImplicitly(ImplicitUseKindFlags.InstantiatedNoFixedConstructorSignature)] - public abstract class ImplicitlyChangingTextLanguageDefinition : HitCountingResourceDefinition - { - internal const string Suffix = " (changed)"; + internal const string Suffix = " (changed)"; - private readonly IMongoDataAccess _mongoDataAccess; + private readonly IMongoDataAccess _mongoDataAccess; - protected ImplicitlyChangingTextLanguageDefinition(IResourceGraph resourceGraph, ResourceDefinitionHitCounter hitCounter, - IMongoDataAccess mongoDataAccess) - : base(resourceGraph, hitCounter) - { - _mongoDataAccess = mongoDataAccess; - } + protected ImplicitlyChangingTextLanguageDefinition(IResourceGraph resourceGraph, ResourceDefinitionHitCounter hitCounter, IMongoDataAccess mongoDataAccess) + : base(resourceGraph, hitCounter) + { + _mongoDataAccess = mongoDataAccess; + } - public override async Task OnWriteSucceededAsync(TextLanguage resource, WriteOperationKind writeOperation, CancellationToken cancellationToken) - { - await base.OnWriteSucceededAsync(resource, writeOperation, cancellationToken); + public override async Task OnWriteSucceededAsync(TextLanguage resource, WriteOperationKind writeOperation, CancellationToken cancellationToken) + { + await base.OnWriteSucceededAsync(resource, writeOperation, cancellationToken); - if (writeOperation is not WriteOperationKind.DeleteResource) - { - resource.IsoCode += Suffix; + if (writeOperation is not WriteOperationKind.DeleteResource) + { + resource.IsoCode += Suffix; - FilterDefinition filter = Builders.Filter.Eq(item => item.Id, resource.Id); + FilterDefinition filter = Builders.Filter.Eq(item => item.Id, resource.Id); - IMongoCollection collection = _mongoDataAccess.MongoDatabase.GetCollection(nameof(TextLanguage)); - await collection.ReplaceOneAsync(_mongoDataAccess.ActiveSession, filter, resource, cancellationToken: cancellationToken); - } + IMongoCollection collection = _mongoDataAccess.MongoDatabase.GetCollection(nameof(TextLanguage)); + await collection.ReplaceOneAsync(_mongoDataAccess.ActiveSession, filter, resource, cancellationToken: cancellationToken); } } } diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Meta/AtomicResourceMetaTests.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Meta/AtomicResourceMetaTests.cs index a701256..ed87024 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Meta/AtomicResourceMetaTests.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Meta/AtomicResourceMetaTests.cs @@ -112,10 +112,10 @@ public async Task Returns_resource_meta_in_update_resource_with_side_effects() TextLanguage existingLanguage = _fakers.TextLanguage.Generate(); - await _testContext.RunOnDatabaseAsync(async dbContext => + await _testContext.RunOnDatabaseAsync(dbContext => { dbContext.TextLanguages.Add(existingLanguage); - await dbContext.SaveChangesAsync(); + return dbContext.SaveChangesAsync(); }); var requestBody = new diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Meta/TextLanguageMetaDefinition.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Meta/TextLanguageMetaDefinition.cs index ef3db2a..bf1bd66 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Meta/TextLanguageMetaDefinition.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Meta/TextLanguageMetaDefinition.cs @@ -5,7 +5,7 @@ namespace JsonApiDotNetCoreMongoDbTests.IntegrationTests.AtomicOperations.Meta; [UsedImplicitly(ImplicitUseKindFlags.InstantiatedNoFixedConstructorSignature)] -public sealed class TextLanguageMetaDefinition : ContainerTypeToHideFromAutoDiscovery.ImplicitlyChangingTextLanguageDefinition +public sealed class TextLanguageMetaDefinition : ImplicitlyChangingTextLanguageDefinition { internal const string NoticeText = "See https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes for ISO 639-1 language codes."; diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Transactions/AtomicRollbackTests.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Transactions/AtomicRollbackTests.cs index b9db4b1..26ea797 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Transactions/AtomicRollbackTests.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Transactions/AtomicRollbackTests.cs @@ -26,10 +26,7 @@ public async Task Can_rollback_created_resource_on_error() string newArtistName = _fakers.Performer.Generate().ArtistName!; DateTimeOffset newBornAt = _fakers.Performer.Generate().BornAt; - await _testContext.RunOnDatabaseAsync(async dbContext => - { - await dbContext.ClearTableAsync(); - }); + await _testContext.RunOnDatabaseAsync(dbContext => dbContext.ClearTableAsync()); string unknownPerformerId = Unknown.StringId.For(); @@ -94,10 +91,10 @@ public async Task Can_rollback_updated_resource_on_error() string newArtistName = _fakers.Performer.Generate().ArtistName!; - await _testContext.RunOnDatabaseAsync(async dbContext => + await _testContext.RunOnDatabaseAsync(dbContext => { dbContext.Performers.Add(existingPerformer); - await dbContext.SaveChangesAsync(); + return dbContext.SaveChangesAsync(); }); string unknownPerformerId = Unknown.StringId.For(); diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Transactions/AtomicTransactionConsistencyTests.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Transactions/AtomicTransactionConsistencyTests.cs index 4d89d74..5475fcb 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Transactions/AtomicTransactionConsistencyTests.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Transactions/AtomicTransactionConsistencyTests.cs @@ -2,7 +2,7 @@ using FluentAssertions; using JsonApiDotNetCore.Configuration; using JsonApiDotNetCore.Serialization.Objects; -using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; using TestBuildingBlocks; using Xunit; @@ -17,15 +17,17 @@ public AtomicTransactionConsistencyTests(IntegrationTestContext(); - testContext.ConfigureServicesAfterStartup(services => + testContext.ConfigureServices(services => { - services.AddSingleton(); + services.TryAddSingleton(); - services.AddResourceRepository(); - services.AddResourceRepository(); - services.AddResourceRepository(); + services.AddResourceRepository(); + services.AddResourceRepository(); + services.AddResourceRepository(); }); } diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Transactions/LyricRepository.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Transactions/LyricRepository.cs index 93e31b2..d738e8d 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Transactions/LyricRepository.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Transactions/LyricRepository.cs @@ -9,30 +9,25 @@ namespace JsonApiDotNetCoreMongoDbTests.IntegrationTests.AtomicOperations.Transactions; -[UsedImplicitly] -internal sealed partial class ContainerTypeToHideFromAutoDiscovery +[UsedImplicitly(ImplicitUseKindFlags.InstantiatedNoFixedConstructorSignature)] +public sealed class LyricRepository : MongoRepository, IAsyncDisposable { - [UsedImplicitly(ImplicitUseKindFlags.InstantiatedNoFixedConstructorSignature)] - public sealed class LyricRepository : MongoRepository, IAsyncDisposable - { - private readonly IOperationsTransaction _transaction; + private readonly IOperationsTransaction _transaction; - public override string TransactionId => _transaction.TransactionId; + public override string TransactionId => _transaction.TransactionId; - public LyricRepository(IMongoDataAccess mongoDataAccess, ITargetedFields targetedFields, IResourceGraph resourceGraph, IResourceFactory resourceFactory, - IEnumerable constraintProviders, IResourceDefinitionAccessor resourceDefinitionAccessor, - IQueryableBuilder queryableBuilder) - : base(mongoDataAccess, targetedFields, resourceGraph, resourceFactory, constraintProviders, resourceDefinitionAccessor, queryableBuilder) - { - IMongoDataAccess otherDataAccess = new MongoDataAccess(mongoDataAccess.MongoDatabase); + public LyricRepository(IMongoDataAccess mongoDataAccess, ITargetedFields targetedFields, IResourceGraph resourceGraph, IResourceFactory resourceFactory, + IEnumerable constraintProviders, IResourceDefinitionAccessor resourceDefinitionAccessor, IQueryableBuilder queryableBuilder) + : base(mongoDataAccess, targetedFields, resourceGraph, resourceFactory, constraintProviders, resourceDefinitionAccessor, queryableBuilder) + { + IMongoDataAccess otherDataAccess = new MongoDataAccess(mongoDataAccess.MongoDatabase); - var factory = new MongoTransactionFactory(otherDataAccess); - _transaction = factory.BeginTransactionAsync(CancellationToken.None).Result; - } + var factory = new MongoTransactionFactory(otherDataAccess); + _transaction = factory.BeginTransactionAsync(CancellationToken.None).Result; + } - public async ValueTask DisposeAsync() - { - await _transaction.DisposeAsync(); - } + public ValueTask DisposeAsync() + { + return _transaction.DisposeAsync(); } } diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Transactions/MusicTrackRepository.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Transactions/MusicTrackRepository.cs index 5d40f37..9595112 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Transactions/MusicTrackRepository.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Transactions/MusicTrackRepository.cs @@ -7,18 +7,15 @@ namespace JsonApiDotNetCoreMongoDbTests.IntegrationTests.AtomicOperations.Transactions; -internal sealed partial class ContainerTypeToHideFromAutoDiscovery +[UsedImplicitly(ImplicitUseKindFlags.InstantiatedNoFixedConstructorSignature)] +public sealed class MusicTrackRepository : MongoRepository { - [UsedImplicitly(ImplicitUseKindFlags.InstantiatedNoFixedConstructorSignature)] - public sealed class MusicTrackRepository : MongoRepository - { - public override string? TransactionId => null; + public override string? TransactionId => null; - public MusicTrackRepository(IMongoDataAccess mongoDataAccess, ITargetedFields targetedFields, IResourceGraph resourceGraph, - IResourceFactory resourceFactory, IEnumerable constraintProviders, IResourceDefinitionAccessor resourceDefinitionAccessor, - IQueryableBuilder queryableBuilder) - : base(mongoDataAccess, targetedFields, resourceGraph, resourceFactory, constraintProviders, resourceDefinitionAccessor, queryableBuilder) - { - } + public MusicTrackRepository(IMongoDataAccess mongoDataAccess, ITargetedFields targetedFields, IResourceGraph resourceGraph, + IResourceFactory resourceFactory, IEnumerable constraintProviders, IResourceDefinitionAccessor resourceDefinitionAccessor, + IQueryableBuilder queryableBuilder) + : base(mongoDataAccess, targetedFields, resourceGraph, resourceFactory, constraintProviders, resourceDefinitionAccessor, queryableBuilder) + { } } diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Transactions/PerformerRepository.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Transactions/PerformerRepository.cs index c4d2e26..2f73d74 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Transactions/PerformerRepository.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Transactions/PerformerRepository.cs @@ -6,60 +6,56 @@ namespace JsonApiDotNetCoreMongoDbTests.IntegrationTests.AtomicOperations.Transactions; -internal sealed partial class ContainerTypeToHideFromAutoDiscovery +[UsedImplicitly(ImplicitUseKindFlags.InstantiatedNoFixedConstructorSignature)] +public sealed class PerformerRepository : IResourceRepository { - [UsedImplicitly(ImplicitUseKindFlags.InstantiatedNoFixedConstructorSignature)] - public sealed class PerformerRepository : IResourceRepository + public Task> GetAsync(QueryLayer queryLayer, CancellationToken cancellationToken) { - public Task> GetAsync(QueryLayer queryLayer, CancellationToken cancellationToken) - { - throw new NotImplementedException(); - } + throw new NotImplementedException(); + } - public Task CountAsync(FilterExpression? filter, CancellationToken cancellationToken) - { - throw new NotImplementedException(); - } + public Task CountAsync(FilterExpression? filter, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } - public Task GetForCreateAsync(Type resourceClrType, string? id, CancellationToken cancellationToken) - { - throw new NotImplementedException(); - } + public Task GetForCreateAsync(Type resourceClrType, string? id, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } - public Task CreateAsync(Performer resourceFromRequest, Performer resourceForDatabase, CancellationToken cancellationToken) - { - throw new NotImplementedException(); - } + public Task CreateAsync(Performer resourceFromRequest, Performer resourceForDatabase, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } - public Task GetForUpdateAsync(QueryLayer queryLayer, CancellationToken cancellationToken) - { - throw new NotImplementedException(); - } + public Task GetForUpdateAsync(QueryLayer queryLayer, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } - public Task UpdateAsync(Performer resourceFromRequest, Performer resourceFromDatabase, CancellationToken cancellationToken) - { - throw new NotImplementedException(); - } + public Task UpdateAsync(Performer resourceFromRequest, Performer resourceFromDatabase, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } - public Task DeleteAsync(Performer? resourceFromDatabase, string? id, CancellationToken cancellationToken) - { - throw new NotImplementedException(); - } + public Task DeleteAsync(Performer? resourceFromDatabase, string? id, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } - public Task SetRelationshipAsync(Performer leftResource, object? rightValue, CancellationToken cancellationToken) - { - throw new NotImplementedException(); - } + public Task SetRelationshipAsync(Performer leftResource, object? rightValue, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } - public Task AddToToManyRelationshipAsync(Performer? leftResource, string? leftId, ISet rightResourceIds, - CancellationToken cancellationToken) - { - throw new NotImplementedException(); - } + public Task AddToToManyRelationshipAsync(Performer? leftResource, string? leftId, ISet rightResourceIds, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } - public Task RemoveFromToManyRelationshipAsync(Performer leftResource, ISet rightResourceIds, CancellationToken cancellationToken) - { - throw new NotImplementedException(); - } + public Task RemoveFromToManyRelationshipAsync(Performer leftResource, ISet rightResourceIds, CancellationToken cancellationToken) + { + throw new NotImplementedException(); } } diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Updating/Relationships/AtomicAddToToManyRelationshipTests.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Updating/Relationships/AtomicAddToToManyRelationshipTests.cs index bf4edda..d15f9d0 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Updating/Relationships/AtomicAddToToManyRelationshipTests.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Updating/Relationships/AtomicAddToToManyRelationshipTests.cs @@ -24,11 +24,11 @@ public async Task Cannot_add_to_OneToMany_relationship() MusicTrack existingTrack = _fakers.MusicTrack.Generate(); Performer existingPerformer = _fakers.Performer.Generate(); - await _testContext.RunOnDatabaseAsync(async dbContext => + await _testContext.RunOnDatabaseAsync(dbContext => { dbContext.Performers.Add(existingPerformer); dbContext.MusicTracks.Add(existingTrack); - await dbContext.SaveChangesAsync(); + return dbContext.SaveChangesAsync(); }); var requestBody = new @@ -81,11 +81,11 @@ public async Task Cannot_add_to_ManyToMany_relationship() Playlist existingPlaylist = _fakers.Playlist.Generate(); MusicTrack existingTrack = _fakers.MusicTrack.Generate(); - await _testContext.RunOnDatabaseAsync(async dbContext => + await _testContext.RunOnDatabaseAsync(dbContext => { dbContext.MusicTracks.Add(existingTrack); dbContext.Playlists.Add(existingPlaylist); - await dbContext.SaveChangesAsync(); + return dbContext.SaveChangesAsync(); }); var requestBody = new diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Updating/Relationships/AtomicRemoveFromToManyRelationshipTests.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Updating/Relationships/AtomicRemoveFromToManyRelationshipTests.cs index cb17dcd..857f7c5 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Updating/Relationships/AtomicRemoveFromToManyRelationshipTests.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Updating/Relationships/AtomicRemoveFromToManyRelationshipTests.cs @@ -24,11 +24,11 @@ public async Task Cannot_remove_from_OneToMany_relationship() MusicTrack existingTrack = _fakers.MusicTrack.Generate(); existingTrack.Performers = _fakers.Performer.Generate(1); - await _testContext.RunOnDatabaseAsync(async dbContext => + await _testContext.RunOnDatabaseAsync(dbContext => { dbContext.Performers.Add(existingTrack.Performers[0]); dbContext.MusicTracks.Add(existingTrack); - await dbContext.SaveChangesAsync(); + return dbContext.SaveChangesAsync(); }); var requestBody = new @@ -81,11 +81,11 @@ public async Task Cannot_remove_from_ManyToMany_relationship() Playlist existingPlaylist = _fakers.Playlist.Generate(); existingPlaylist.Tracks = _fakers.MusicTrack.Generate(1); - await _testContext.RunOnDatabaseAsync(async dbContext => + await _testContext.RunOnDatabaseAsync(dbContext => { dbContext.MusicTracks.Add(existingPlaylist.Tracks[0]); dbContext.Playlists.Add(existingPlaylist); - await dbContext.SaveChangesAsync(); + return dbContext.SaveChangesAsync(); }); var requestBody = new diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Updating/Relationships/AtomicReplaceToManyRelationshipTests.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Updating/Relationships/AtomicReplaceToManyRelationshipTests.cs index 27d679a..b716339 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Updating/Relationships/AtomicReplaceToManyRelationshipTests.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Updating/Relationships/AtomicReplaceToManyRelationshipTests.cs @@ -24,11 +24,11 @@ public async Task Cannot_replace_OneToMany_relationship() MusicTrack existingTrack = _fakers.MusicTrack.Generate(); Performer existingPerformer = _fakers.Performer.Generate(); - await _testContext.RunOnDatabaseAsync(async dbContext => + await _testContext.RunOnDatabaseAsync(dbContext => { dbContext.Performers.Add(existingPerformer); dbContext.MusicTracks.Add(existingTrack); - await dbContext.SaveChangesAsync(); + return dbContext.SaveChangesAsync(); }); var requestBody = new @@ -81,11 +81,11 @@ public async Task Cannot_replace_ManyToMany_relationship() Playlist existingPlaylist = _fakers.Playlist.Generate(); MusicTrack existingTrack = _fakers.MusicTrack.Generate(); - await _testContext.RunOnDatabaseAsync(async dbContext => + await _testContext.RunOnDatabaseAsync(dbContext => { dbContext.MusicTracks.Add(existingTrack); dbContext.Playlists.Add(existingPlaylist); - await dbContext.SaveChangesAsync(); + return dbContext.SaveChangesAsync(); }); var requestBody = new diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Updating/Relationships/AtomicUpdateToOneRelationshipTests.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Updating/Relationships/AtomicUpdateToOneRelationshipTests.cs index 0f80aee..dccab27 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Updating/Relationships/AtomicUpdateToOneRelationshipTests.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Updating/Relationships/AtomicUpdateToOneRelationshipTests.cs @@ -24,11 +24,11 @@ public async Task Cannot_create_ManyToOne_relationship() MusicTrack existingTrack = _fakers.MusicTrack.Generate(); RecordCompany existingCompany = _fakers.RecordCompany.Generate(); - await _testContext.RunOnDatabaseAsync(async dbContext => + await _testContext.RunOnDatabaseAsync(dbContext => { dbContext.RecordCompanies.Add(existingCompany); dbContext.MusicTracks.Add(existingTrack); - await dbContext.SaveChangesAsync(); + return dbContext.SaveChangesAsync(); }); var requestBody = new diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Updating/Resources/AtomicReplaceToManyRelationshipTests.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Updating/Resources/AtomicReplaceToManyRelationshipTests.cs index 162bacb..833bdd3 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Updating/Resources/AtomicReplaceToManyRelationshipTests.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Updating/Resources/AtomicReplaceToManyRelationshipTests.cs @@ -24,11 +24,11 @@ public async Task Cannot_replace_ToMany_relationship() MusicTrack existingTrack = _fakers.MusicTrack.Generate(); Performer existingPerformer = _fakers.Performer.Generate(); - await _testContext.RunOnDatabaseAsync(async dbContext => + await _testContext.RunOnDatabaseAsync(dbContext => { dbContext.Performers.Add(existingPerformer); dbContext.MusicTracks.Add(existingTrack); - await dbContext.SaveChangesAsync(); + return dbContext.SaveChangesAsync(); }); var requestBody = new diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Updating/Resources/AtomicUpdateResourceTests.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Updating/Resources/AtomicUpdateResourceTests.cs index a6cec5b..7ae1426 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Updating/Resources/AtomicUpdateResourceTests.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Updating/Resources/AtomicUpdateResourceTests.cs @@ -89,10 +89,10 @@ public async Task Can_update_resource_without_attributes_or_relationships() // Arrange MusicTrack existingTrack = _fakers.MusicTrack.Generate(); - await _testContext.RunOnDatabaseAsync(async dbContext => + await _testContext.RunOnDatabaseAsync(dbContext => { dbContext.MusicTracks.Add(existingTrack); - await dbContext.SaveChangesAsync(); + return dbContext.SaveChangesAsync(); }); var requestBody = new @@ -144,10 +144,10 @@ public async Task Can_partially_update_resource_without_side_effects() string newGenre = _fakers.MusicTrack.Generate().Genre!; - await _testContext.RunOnDatabaseAsync(async dbContext => + await _testContext.RunOnDatabaseAsync(dbContext => { dbContext.MusicTracks.Add(existingTrack); - await dbContext.SaveChangesAsync(); + return dbContext.SaveChangesAsync(); }); var requestBody = new @@ -202,10 +202,10 @@ public async Task Can_completely_update_resource_without_side_effects() string newGenre = _fakers.MusicTrack.Generate().Genre!; DateTimeOffset newReleasedAt = _fakers.MusicTrack.Generate().ReleasedAt; - await _testContext.RunOnDatabaseAsync(async dbContext => + await _testContext.RunOnDatabaseAsync(dbContext => { dbContext.MusicTracks.Add(existingTrack); - await dbContext.SaveChangesAsync(); + return dbContext.SaveChangesAsync(); }); var requestBody = new @@ -259,10 +259,10 @@ public async Task Can_update_resource_with_side_effects() TextLanguage existingLanguage = _fakers.TextLanguage.Generate(); string newIsoCode = _fakers.TextLanguage.Generate().IsoCode!; - await _testContext.RunOnDatabaseAsync(async dbContext => + await _testContext.RunOnDatabaseAsync(dbContext => { dbContext.TextLanguages.Add(existingLanguage); - await dbContext.SaveChangesAsync(); + return dbContext.SaveChangesAsync(); }); var requestBody = new @@ -295,7 +295,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => responseDocument.Results.ShouldHaveCount(1); - string isoCode = $"{newIsoCode}{ContainerTypeToHideFromAutoDiscovery.ImplicitlyChangingTextLanguageDefinition.Suffix}"; + string isoCode = $"{newIsoCode}{ImplicitlyChangingTextLanguageDefinition.Suffix}"; responseDocument.Results[0].Data.SingleValue.ShouldNotBeNull().With(resource => { diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Updating/Resources/AtomicUpdateToOneRelationshipTests.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Updating/Resources/AtomicUpdateToOneRelationshipTests.cs index 0e0562a..df60664 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Updating/Resources/AtomicUpdateToOneRelationshipTests.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/AtomicOperations/Updating/Resources/AtomicUpdateToOneRelationshipTests.cs @@ -24,11 +24,11 @@ public async Task Cannot_create_ToOne_relationship() Lyric existingLyric = _fakers.Lyric.Generate(); MusicTrack existingTrack = _fakers.MusicTrack.Generate(); - await _testContext.RunOnDatabaseAsync(async dbContext => + await _testContext.RunOnDatabaseAsync(dbContext => { dbContext.MusicTracks.Add(existingTrack); dbContext.Lyrics.Add(existingLyric); - await dbContext.SaveChangesAsync(); + return dbContext.SaveChangesAsync(); }); var requestBody = new diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/Meta/ResourceMetaTests.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/Meta/ResourceMetaTests.cs index 3a3edca..d92419c 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/Meta/ResourceMetaTests.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/Meta/ResourceMetaTests.cs @@ -1,7 +1,9 @@ using System.Net; using FluentAssertions; +using JsonApiDotNetCore.Configuration; using JsonApiDotNetCore.Serialization.Objects; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; using TestBuildingBlocks; using Xunit; @@ -16,11 +18,14 @@ public ResourceMetaTests(IntegrationTestContext { _testContext = testContext; + testContext.UseResourceTypesInNamespace(typeof(SupportTicket).Namespace); + testContext.UseController(); - testContext.ConfigureServicesAfterStartup(services => + testContext.ConfigureServices(services => { - services.AddSingleton(); + services.TryAddSingleton(); + services.AddResourceDefinition(); }); var hitCounter = _testContext.Factory.Services.GetRequiredService(); diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/Meta/TopLevelCountTests.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/Meta/TopLevelCountTests.cs index c486d0d..cd122ae 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/Meta/TopLevelCountTests.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/Meta/TopLevelCountTests.cs @@ -4,6 +4,7 @@ using JsonApiDotNetCore.Resources; using JsonApiDotNetCore.Serialization.Objects; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; using TestBuildingBlocks; using Xunit; @@ -18,13 +19,11 @@ public TopLevelCountTests(IntegrationTestContext { _testContext = testContext; + testContext.UseResourceTypesInNamespace(typeof(SupportTicket).Namespace); + testContext.UseController(); - testContext.ConfigureServicesAfterStartup(services => - { - services.AddSingleton(); - services.AddScoped(typeof(IResourceChangeTracker<>), typeof(NeverSameResourceChangeTracker<>)); - }); + testContext.ConfigureServices(services => services.TryAddScoped(typeof(IResourceChangeTracker<>), typeof(NeverSameResourceChangeTracker<>))); var options = (JsonApiOptions)testContext.Factory.Services.GetRequiredService(); options.IncludeTotalResourceCount = true; @@ -60,10 +59,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => public async Task Renders_resource_count_for_empty_collection() { // Arrange - await _testContext.RunOnDatabaseAsync(async dbContext => - { - await dbContext.ClearTableAsync(); - }); + await _testContext.RunOnDatabaseAsync(dbContext => dbContext.ClearTableAsync()); const string route = "/supportTickets"; @@ -115,10 +111,10 @@ public async Task Hides_resource_count_in_update_resource_response() string newDescription = _fakers.SupportTicket.Generate().Description; - await _testContext.RunOnDatabaseAsync(async dbContext => + await _testContext.RunOnDatabaseAsync(dbContext => { dbContext.SupportTickets.Add(existingTicket); - await dbContext.SaveChangesAsync(); + return dbContext.SaveChangesAsync(); }); var requestBody = new diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/QueryStrings/Filtering/FilterDataTypeTests.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/QueryStrings/Filtering/FilterDataTypeTests.cs index 5dc1442..a74e6ee 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/QueryStrings/Filtering/FilterDataTypeTests.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/QueryStrings/Filtering/FilterDataTypeTests.cs @@ -19,6 +19,8 @@ public FilterDataTypeTests(IntegrationTestContext(); } diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/QueryStrings/Filtering/FilterDepthTests.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/QueryStrings/Filtering/FilterDepthTests.cs index 888cd6c..fccf739 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/QueryStrings/Filtering/FilterDepthTests.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/QueryStrings/Filtering/FilterDepthTests.cs @@ -15,6 +15,8 @@ public FilterDepthTests(IntegrationTestContext(); testContext.UseController(); } diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/QueryStrings/Filtering/FilterOperatorTests.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/QueryStrings/Filtering/FilterOperatorTests.cs index 60e10e7..efc7075 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/QueryStrings/Filtering/FilterOperatorTests.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/QueryStrings/Filtering/FilterOperatorTests.cs @@ -39,6 +39,8 @@ public FilterOperatorTests(IntegrationTestContext(); } diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/QueryStrings/Filtering/FilterTests.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/QueryStrings/Filtering/FilterTests.cs index 9be84ed..c432a77 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/QueryStrings/Filtering/FilterTests.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/QueryStrings/Filtering/FilterTests.cs @@ -15,6 +15,8 @@ public FilterTests(IntegrationTestContext { _testContext = testContext; + testContext.UseResourceTypesInNamespace(typeof(Blog).Namespace); + testContext.UseController(); } diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/QueryStrings/Includes/IncludeTests.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/QueryStrings/Includes/IncludeTests.cs index 63c5c1f..2fcbfe5 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/QueryStrings/Includes/IncludeTests.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/QueryStrings/Includes/IncludeTests.cs @@ -14,6 +14,8 @@ public IncludeTests(IntegrationTestContext(); } diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/QueryStrings/Pagination/PaginationWithTotalCountTests.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/QueryStrings/Pagination/PaginationWithTotalCountTests.cs index d638555..96e031b 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/QueryStrings/Pagination/PaginationWithTotalCountTests.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/QueryStrings/Pagination/PaginationWithTotalCountTests.cs @@ -19,6 +19,8 @@ public PaginationWithTotalCountTests(IntegrationTestContext(); var options = (JsonApiOptions)testContext.Factory.Services.GetRequiredService(); diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/QueryStrings/Pagination/RangeValidationTests.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/QueryStrings/Pagination/RangeValidationTests.cs index 63ec7c6..28a7c06 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/QueryStrings/Pagination/RangeValidationTests.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/QueryStrings/Pagination/RangeValidationTests.cs @@ -15,6 +15,8 @@ public RangeValidationTests(IntegrationTestContext(); } diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/QueryStrings/Sorting/SortTests.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/QueryStrings/Sorting/SortTests.cs index f0846b7..a5269d7 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/QueryStrings/Sorting/SortTests.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/QueryStrings/Sorting/SortTests.cs @@ -15,6 +15,8 @@ public SortTests(IntegrationTestContext t { _testContext = testContext; + testContext.UseResourceTypesInNamespace(typeof(Blog).Namespace); + testContext.UseController(); testContext.UseController(); testContext.UseController(); diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/QueryStrings/SparseFieldSets/ResourceCaptureStore.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/QueryStrings/SparseFieldSets/ResourceCaptureStore.cs index 4eeea37..56e7ab9 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/QueryStrings/SparseFieldSets/ResourceCaptureStore.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/QueryStrings/SparseFieldSets/ResourceCaptureStore.cs @@ -4,7 +4,7 @@ namespace JsonApiDotNetCoreMongoDbTests.IntegrationTests.QueryStrings.SparseFiel public sealed class ResourceCaptureStore { - internal List Resources { get; } = new(); + internal List Resources { get; } = []; internal void Add(IEnumerable resources) { diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/QueryStrings/SparseFieldSets/SparseFieldSetTests.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/QueryStrings/SparseFieldSets/SparseFieldSetTests.cs index dca4609..b61ebac 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/QueryStrings/SparseFieldSets/SparseFieldSetTests.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/QueryStrings/SparseFieldSets/SparseFieldSetTests.cs @@ -3,6 +3,7 @@ using JsonApiDotNetCore.Configuration; using JsonApiDotNetCore.Serialization.Objects; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; using TestBuildingBlocks; using Xunit; @@ -17,13 +18,15 @@ public SparseFieldSetTests(IntegrationTestContext(); testContext.UseController(); testContext.UseController(); - testContext.ConfigureServicesAfterStartup(services => + testContext.ConfigureServices(services => { - services.AddSingleton(); + services.TryAddSingleton(); services.AddResourceRepository>(); services.AddResourceRepository>(); @@ -82,7 +85,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => responseDocument.Data.ManyValue[0].Attributes.ShouldContainKey("caption").With(value => value.Should().Be(post.Caption)); responseDocument.Data.ManyValue[0].Relationships.Should().BeNull(); - var postCaptured = (BlogPost)store.Resources.Should().ContainSingle(resource => resource is BlogPost).And.Subject.Single(); + var postCaptured = (BlogPost)store.Resources.Should().ContainSingle(resource => resource is BlogPost).Which; postCaptured.Caption.Should().Be(post.Caption); postCaptured.Url.Should().BeNull(); } @@ -117,10 +120,10 @@ public async Task Can_select_attribute_in_primary_resource_by_ID() BlogPost post = _fakers.BlogPost.Generate(); - await _testContext.RunOnDatabaseAsync(async dbContext => + await _testContext.RunOnDatabaseAsync(dbContext => { dbContext.Posts.Add(post); - await dbContext.SaveChangesAsync(); + return dbContext.SaveChangesAsync(); }); string route = $"/blogPosts/{post.StringId}?fields[blogPosts]=url"; @@ -137,7 +140,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => responseDocument.Data.SingleValue.Attributes.ShouldContainKey("url").With(value => value.Should().Be(post.Url)); responseDocument.Data.SingleValue.Relationships.Should().BeNull(); - var postCaptured = (BlogPost)store.Resources.Should().ContainSingle(resource => resource is BlogPost).And.Subject.Single(); + var postCaptured = (BlogPost)store.Resources.Should().ContainSingle(resource => resource is BlogPost).Which; postCaptured.Url.Should().Be(post.Url); postCaptured.Caption.Should().BeNull(); } @@ -148,10 +151,10 @@ public async Task Cannot_select_fields_of_ManyToOne_relationship() // Arrange BlogPost post = _fakers.BlogPost.Generate(); - await _testContext.RunOnDatabaseAsync(async dbContext => + await _testContext.RunOnDatabaseAsync(dbContext => { dbContext.Posts.Add(post); - await dbContext.SaveChangesAsync(); + return dbContext.SaveChangesAsync(); }); string route = $"/blogPosts/{post.StringId}?fields[webAccounts]=displayName,emailAddress,preferences"; @@ -177,10 +180,10 @@ public async Task Cannot_select_fields_of_OneToMany_relationship() // Arrange WebAccount account = _fakers.WebAccount.Generate(); - await _testContext.RunOnDatabaseAsync(async dbContext => + await _testContext.RunOnDatabaseAsync(dbContext => { dbContext.Accounts.Add(account); - await dbContext.SaveChangesAsync(); + return dbContext.SaveChangesAsync(); }); string route = $"/webAccounts/{account.StringId}?fields[blogPosts]=caption,labels"; @@ -206,10 +209,10 @@ public async Task Cannot_select_fields_of_ManyToMany_relationship() // Arrange BlogPost post = _fakers.BlogPost.Generate(); - await _testContext.RunOnDatabaseAsync(async dbContext => + await _testContext.RunOnDatabaseAsync(dbContext => { dbContext.Posts.Add(post); - await dbContext.SaveChangesAsync(); + return dbContext.SaveChangesAsync(); }); string route = $"/blogPosts/{post.StringId}?fields[labels]=color"; @@ -259,7 +262,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => responseDocument.Data.ManyValue[0].Attributes.ShouldContainKey("caption").With(value => value.Should().Be(post.Caption)); responseDocument.Data.ManyValue[0].Relationships.Should().BeNull(); - var postCaptured = (BlogPost)store.Resources.Should().ContainSingle(resource => resource is BlogPost).And.Subject.Single(); + var postCaptured = (BlogPost)store.Resources.Should().ContainSingle(resource => resource is BlogPost).Which; postCaptured.Id.Should().Be(post.Id); postCaptured.Caption.Should().Be(post.Caption); postCaptured.Url.Should().BeNull(); @@ -294,7 +297,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => responseDocument.Data.ManyValue[0].Attributes.Should().BeNull(); responseDocument.Data.ManyValue[0].Relationships.Should().BeNull(); - var postCaptured = (BlogPost)store.Resources.Should().ContainSingle(resource => resource is BlogPost).And.Subject.Single(); + var postCaptured = (BlogPost)store.Resources.Should().ContainSingle(resource => resource is BlogPost).Which; postCaptured.Id.Should().Be(post.Id); postCaptured.Url.Should().BeNull(); } @@ -309,10 +312,10 @@ public async Task Fetches_all_scalar_properties_when_fieldset_contains_readonly_ Blog blog = _fakers.Blog.Generate(); blog.IsPublished = true; - await _testContext.RunOnDatabaseAsync(async dbContext => + await _testContext.RunOnDatabaseAsync(dbContext => { dbContext.Blogs.Add(blog); - await dbContext.SaveChangesAsync(); + return dbContext.SaveChangesAsync(); }); string route = $"/blogs/{blog.StringId}?fields[blogs]=showAdvertisements"; @@ -329,7 +332,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => responseDocument.Data.SingleValue.Attributes.ShouldContainKey("showAdvertisements").With(value => value.Should().Be(blog.ShowAdvertisements)); responseDocument.Data.SingleValue.Relationships.Should().BeNull(); - var blogCaptured = (Blog)store.Resources.Should().ContainSingle(resource => resource is Blog).And.Subject.Single(); + var blogCaptured = (Blog)store.Resources.Should().ContainSingle(resource => resource is Blog).Which; blogCaptured.ShowAdvertisements.Should().Be(blog.ShowAdvertisements); blogCaptured.IsPublished.Should().Be(blog.IsPublished); blogCaptured.Title.Should().Be(blog.Title); diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Creating/CreateResourceTests.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Creating/CreateResourceTests.cs index 7797e79..ccc1ec6 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Creating/CreateResourceTests.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Creating/CreateResourceTests.cs @@ -15,6 +15,8 @@ public CreateResourceTests(IntegrationTestContext(); testContext.UseController(); testContext.UseController(); diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Creating/CreateResourceWithClientGeneratedIdTests.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Creating/CreateResourceWithClientGeneratedIdTests.cs index 9993e03..c763529 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Creating/CreateResourceWithClientGeneratedIdTests.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Creating/CreateResourceWithClientGeneratedIdTests.cs @@ -17,13 +17,12 @@ public CreateResourceWithClientGeneratedIdTests(IntegrationTestContext(); testContext.UseController(); - testContext.ConfigureServicesAfterStartup(services => - { - services.AddResourceDefinition(); - }); + testContext.ConfigureServices(services => services.AddResourceDefinition()); var options = (JsonApiOptions)testContext.Factory.Services.GetRequiredService(); options.ClientIdGeneration = ClientIdGenerationMode.Required; @@ -57,7 +56,7 @@ public async Task Can_create_resource_with_client_generated_string_ID_having_sid // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Created); - string groupName = $"{newGroup.Name}{ContainerTypeToHideFromAutoDiscovery.ImplicitlyChangingWorkItemGroupDefinition.Suffix}"; + string groupName = $"{newGroup.Name}{ImplicitlyChangingWorkItemGroupDefinition.Suffix}"; responseDocument.Data.SingleValue.ShouldNotBeNull(); responseDocument.Data.SingleValue.Type.Should().Be("workItemGroups"); @@ -101,7 +100,7 @@ public async Task Can_create_resource_with_client_generated_string_ID_having_sid // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.Created); - string groupName = $"{newGroup.Name}{ContainerTypeToHideFromAutoDiscovery.ImplicitlyChangingWorkItemGroupDefinition.Suffix}"; + string groupName = $"{newGroup.Name}{ImplicitlyChangingWorkItemGroupDefinition.Suffix}"; responseDocument.Data.SingleValue.ShouldNotBeNull(); responseDocument.Data.SingleValue.Type.Should().Be("workItemGroups"); @@ -203,10 +202,10 @@ public async Task Cannot_create_resource_for_existing_client_generated_ID() string newDisplayName = _fakers.RgbColor.Generate().DisplayName; - await _testContext.RunOnDatabaseAsync(async dbContext => + await _testContext.RunOnDatabaseAsync(dbContext => { dbContext.RgbColors.Add(existingColor); - await dbContext.SaveChangesAsync(); + return dbContext.SaveChangesAsync(); }); var requestBody = new diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Creating/CreateResourceWithToManyRelationshipTests.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Creating/CreateResourceWithToManyRelationshipTests.cs index 626547c..f021d9b 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Creating/CreateResourceWithToManyRelationshipTests.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Creating/CreateResourceWithToManyRelationshipTests.cs @@ -15,6 +15,8 @@ public CreateResourceWithToManyRelationshipTests(IntegrationTestContext(); } @@ -24,10 +26,10 @@ public async Task Cannot_create_resource_with_ToMany_relationship() // Arrange UserAccount? existingUserAccount = _fakers.UserAccount.Generate(); - await _testContext.RunOnDatabaseAsync(async dbContext => + await _testContext.RunOnDatabaseAsync(dbContext => { dbContext.UserAccounts.Add(existingUserAccount); - await dbContext.SaveChangesAsync(); + return dbContext.SaveChangesAsync(); }); var requestBody = new diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Creating/CreateResourceWithToOneRelationshipTests.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Creating/CreateResourceWithToOneRelationshipTests.cs index 337d48a..f02131d 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Creating/CreateResourceWithToOneRelationshipTests.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Creating/CreateResourceWithToOneRelationshipTests.cs @@ -15,6 +15,8 @@ public CreateResourceWithToOneRelationshipTests(IntegrationTestContext(); } @@ -27,11 +29,11 @@ public async Task Cannot_create_resource_with_ToOne_relationship() string newGroupName = _fakers.WorkItemGroup.Generate().Name; - await _testContext.RunOnDatabaseAsync(async dbContext => + await _testContext.RunOnDatabaseAsync(dbContext => { dbContext.RgbColors.Add(existingGroup.Color); dbContext.Groups.Add(existingGroup); - await dbContext.SaveChangesAsync(); + return dbContext.SaveChangesAsync(); }); var requestBody = new diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Deleting/DeleteResourceTests.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Deleting/DeleteResourceTests.cs index 99cac72..c00fd07 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Deleting/DeleteResourceTests.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Deleting/DeleteResourceTests.cs @@ -15,6 +15,8 @@ public DeleteResourceTests(IntegrationTestContext(); } @@ -24,10 +26,10 @@ public async Task Can_delete_existing_resource() // Arrange WorkItem existingWorkItem = _fakers.WorkItem.Generate(); - await _testContext.RunOnDatabaseAsync(async dbContext => + await _testContext.RunOnDatabaseAsync(dbContext => { dbContext.WorkItems.Add(existingWorkItem); - await dbContext.SaveChangesAsync(); + return dbContext.SaveChangesAsync(); }); string route = $"/workItems/{existingWorkItem.StringId}"; diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Fetching/FetchRelationshipTests.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Fetching/FetchRelationshipTests.cs index 884349d..a7f74eb 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Fetching/FetchRelationshipTests.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Fetching/FetchRelationshipTests.cs @@ -15,6 +15,8 @@ public FetchRelationshipTests(IntegrationTestContext(); testContext.UseController(); } @@ -24,10 +26,10 @@ public async Task Cannot_get_ManyToOne_relationship() { WorkItem workItem = _fakers.WorkItem.Generate(); - await _testContext.RunOnDatabaseAsync(async dbContext => + await _testContext.RunOnDatabaseAsync(dbContext => { dbContext.WorkItems.Add(workItem); - await dbContext.SaveChangesAsync(); + return dbContext.SaveChangesAsync(); }); string route = $"/workItems/{workItem.StringId}/relationships/assignee"; @@ -53,10 +55,10 @@ public async Task Cannot_get_OneToMany_relationship() // Arrange UserAccount userAccount = _fakers.UserAccount.Generate(); - await _testContext.RunOnDatabaseAsync(async dbContext => + await _testContext.RunOnDatabaseAsync(dbContext => { dbContext.UserAccounts.Add(userAccount); - await dbContext.SaveChangesAsync(); + return dbContext.SaveChangesAsync(); }); string route = $"/userAccounts/{userAccount.StringId}/relationships/assignedItems"; @@ -82,10 +84,10 @@ public async Task Cannot_get_ManyToMany_relationship() // Arrange WorkItem workItem = _fakers.WorkItem.Generate(); - await _testContext.RunOnDatabaseAsync(async dbContext => + await _testContext.RunOnDatabaseAsync(dbContext => { dbContext.WorkItems.Add(workItem); - await dbContext.SaveChangesAsync(); + return dbContext.SaveChangesAsync(); }); string route = $"/workItems/{workItem.StringId}/relationships/tags"; diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Fetching/FetchResourceTests.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Fetching/FetchResourceTests.cs index e254772..c8ff584 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Fetching/FetchResourceTests.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Fetching/FetchResourceTests.cs @@ -15,6 +15,8 @@ public FetchResourceTests(IntegrationTestContext(); testContext.UseController(); } @@ -63,10 +65,10 @@ public async Task Can_get_primary_resource_by_ID() // Arrange WorkItem workItem = _fakers.WorkItem.Generate(); - await _testContext.RunOnDatabaseAsync(async dbContext => + await _testContext.RunOnDatabaseAsync(dbContext => { dbContext.WorkItems.Add(workItem); - await dbContext.SaveChangesAsync(); + return dbContext.SaveChangesAsync(); }); string route = $"/workItems/{workItem.StringId}"; @@ -114,10 +116,10 @@ public async Task Cannot_get_secondary_ManyToOne_resource() // Arrange WorkItem workItem = _fakers.WorkItem.Generate(); - await _testContext.RunOnDatabaseAsync(async dbContext => + await _testContext.RunOnDatabaseAsync(dbContext => { dbContext.WorkItems.Add(workItem); - await dbContext.SaveChangesAsync(); + return dbContext.SaveChangesAsync(); }); string route = $"/workItems/{workItem.StringId}/assignee"; @@ -143,10 +145,10 @@ public async Task Cannot_get_secondary_OneToMany_resources() // Arrange UserAccount userAccount = _fakers.UserAccount.Generate(); - await _testContext.RunOnDatabaseAsync(async dbContext => + await _testContext.RunOnDatabaseAsync(dbContext => { dbContext.UserAccounts.Add(userAccount); - await dbContext.SaveChangesAsync(); + return dbContext.SaveChangesAsync(); }); string route = $"/userAccounts/{userAccount.StringId}/assignedItems"; @@ -172,10 +174,10 @@ public async Task Cannot_get_secondary_ManyToMany_resources() // Arrange WorkItem workItem = _fakers.WorkItem.Generate(); - await _testContext.RunOnDatabaseAsync(async dbContext => + await _testContext.RunOnDatabaseAsync(dbContext => { dbContext.WorkItems.Add(workItem); - await dbContext.SaveChangesAsync(); + return dbContext.SaveChangesAsync(); }); string route = $"/workItems/{workItem.StringId}/tags"; diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/ImplicitlyChangingWorkItemDefinition.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/ImplicitlyChangingWorkItemDefinition.cs index 4e9f358..61f68e1 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/ImplicitlyChangingWorkItemDefinition.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/ImplicitlyChangingWorkItemDefinition.cs @@ -6,37 +6,35 @@ namespace JsonApiDotNetCoreMongoDbTests.IntegrationTests.ReadWrite; -[UsedImplicitly] -internal sealed partial class ContainerTypeToHideFromAutoDiscovery +/// +/// Used to simulate side effects that occur in the database while saving, typically caused by database triggers. +/// +[UsedImplicitly(ImplicitUseKindFlags.InstantiatedNoFixedConstructorSignature)] +public sealed class ImplicitlyChangingWorkItemDefinition : JsonApiResourceDefinition { - /// - /// Used to simulate side effects that occur in the database while saving, typically caused by database triggers. - /// - [UsedImplicitly(ImplicitUseKindFlags.InstantiatedNoFixedConstructorSignature)] - public sealed class ImplicitlyChangingWorkItemDefinition : JsonApiResourceDefinition - { - internal const string Suffix = " (changed)"; + internal const string Suffix = " (changed)"; - private readonly ReadWriteDbContext _dbContext; + private readonly ReadWriteDbContext _dbContext; - public ImplicitlyChangingWorkItemDefinition(IResourceGraph resourceGraph, ReadWriteDbContext dbContext) - : base(resourceGraph) - { - _dbContext = dbContext; - } + public ImplicitlyChangingWorkItemDefinition(IResourceGraph resourceGraph, ReadWriteDbContext dbContext) + : base(resourceGraph) + { + _dbContext = dbContext; + } - public override async Task OnWriteSucceededAsync(WorkItem resource, WriteOperationKind writeOperation, CancellationToken cancellationToken) + public override Task OnWriteSucceededAsync(WorkItem resource, WriteOperationKind writeOperation, CancellationToken cancellationToken) + { + if (writeOperation is not WriteOperationKind.DeleteResource) { - if (writeOperation is not WriteOperationKind.DeleteResource) + return _dbContext.WorkItems.ExecuteAsync(async collection => { - await _dbContext.WorkItems.ExecuteAsync(async collection => - { - resource.Description += Suffix; + resource.Description += Suffix; - FilterDefinition filter = Builders.Filter.Eq(item => item.Id, resource.Id); - await collection.ReplaceOneAsync(filter, resource, cancellationToken: cancellationToken); - }); - } + FilterDefinition filter = Builders.Filter.Eq(item => item.Id, resource.Id); + await collection.ReplaceOneAsync(filter, resource, cancellationToken: cancellationToken); + }); } + + return Task.CompletedTask; } } diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/ImplicitlyChangingWorkItemGroupDefinition.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/ImplicitlyChangingWorkItemGroupDefinition.cs index e9abd46..3d4e846 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/ImplicitlyChangingWorkItemGroupDefinition.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/ImplicitlyChangingWorkItemGroupDefinition.cs @@ -6,36 +6,35 @@ namespace JsonApiDotNetCoreMongoDbTests.IntegrationTests.ReadWrite; -internal sealed partial class ContainerTypeToHideFromAutoDiscovery +/// +/// Used to simulate side effects that occur in the database while saving, typically caused by database triggers. +/// +[UsedImplicitly(ImplicitUseKindFlags.InstantiatedNoFixedConstructorSignature)] +public sealed class ImplicitlyChangingWorkItemGroupDefinition : JsonApiResourceDefinition { - /// - /// Used to simulate side effects that occur in the database while saving, typically caused by database triggers. - /// - [UsedImplicitly(ImplicitUseKindFlags.InstantiatedNoFixedConstructorSignature)] - public sealed class ImplicitlyChangingWorkItemGroupDefinition : JsonApiResourceDefinition - { - internal const string Suffix = " (changed)"; + internal const string Suffix = " (changed)"; - private readonly ReadWriteDbContext _dbContext; + private readonly ReadWriteDbContext _dbContext; - public ImplicitlyChangingWorkItemGroupDefinition(IResourceGraph resourceGraph, ReadWriteDbContext dbContext) - : base(resourceGraph) - { - _dbContext = dbContext; - } + public ImplicitlyChangingWorkItemGroupDefinition(IResourceGraph resourceGraph, ReadWriteDbContext dbContext) + : base(resourceGraph) + { + _dbContext = dbContext; + } - public override async Task OnWriteSucceededAsync(WorkItemGroup resource, WriteOperationKind writeOperation, CancellationToken cancellationToken) + public override Task OnWriteSucceededAsync(WorkItemGroup resource, WriteOperationKind writeOperation, CancellationToken cancellationToken) + { + if (writeOperation is not WriteOperationKind.DeleteResource) { - if (writeOperation is not WriteOperationKind.DeleteResource) + return _dbContext.Groups.ExecuteAsync(async collection => { - await _dbContext.Groups.ExecuteAsync(async collection => - { - resource.Name += Suffix; + resource.Name += Suffix; - FilterDefinition filter = Builders.Filter.Eq(group => group.Id, resource.Id); - await collection.ReplaceOneAsync(filter, resource, cancellationToken: cancellationToken); - }); - } + FilterDefinition filter = Builders.Filter.Eq(group => group.Id, resource.Id); + await collection.ReplaceOneAsync(filter, resource, cancellationToken: cancellationToken); + }); } + + return Task.CompletedTask; } } diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Updating/Relationships/AddToToManyRelationshipTests.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Updating/Relationships/AddToToManyRelationshipTests.cs index 7487ca4..970c893 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Updating/Relationships/AddToToManyRelationshipTests.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Updating/Relationships/AddToToManyRelationshipTests.cs @@ -15,6 +15,8 @@ public AddToToManyRelationshipTests(IntegrationTestContext(); } @@ -25,11 +27,11 @@ public async Task Cannot_add_to_OneToMany_relationship() WorkItem existingWorkItem = _fakers.WorkItem.Generate(); UserAccount existingSubscriber = _fakers.UserAccount.Generate(); - await _testContext.RunOnDatabaseAsync(async dbContext => + await _testContext.RunOnDatabaseAsync(dbContext => { dbContext.UserAccounts.Add(existingSubscriber); dbContext.WorkItems.Add(existingWorkItem); - await dbContext.SaveChangesAsync(); + return dbContext.SaveChangesAsync(); }); var requestBody = new @@ -68,11 +70,11 @@ public async Task Cannot_add_to_ManyToMany_relationship() WorkItem existingWorkItem = _fakers.WorkItem.Generate(); WorkTag existingTag = _fakers.WorkTag.Generate(); - await _testContext.RunOnDatabaseAsync(async dbContext => + await _testContext.RunOnDatabaseAsync(dbContext => { dbContext.WorkTags.Add(existingTag); dbContext.WorkItems.Add(existingWorkItem); - await dbContext.SaveChangesAsync(); + return dbContext.SaveChangesAsync(); }); var requestBody = new diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Updating/Relationships/RemoveFromToManyRelationshipTests.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Updating/Relationships/RemoveFromToManyRelationshipTests.cs index 0de1b7b..22dd312 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Updating/Relationships/RemoveFromToManyRelationshipTests.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Updating/Relationships/RemoveFromToManyRelationshipTests.cs @@ -15,6 +15,8 @@ public RemoveFromToManyRelationshipTests(IntegrationTestContext(); } @@ -25,11 +27,11 @@ public async Task Cannot_remove_from_OneToMany_relationship() WorkItem existingWorkItem = _fakers.WorkItem.Generate(); existingWorkItem.Subscribers = _fakers.UserAccount.Generate(1).ToHashSet(); - await _testContext.RunOnDatabaseAsync(async dbContext => + await _testContext.RunOnDatabaseAsync(dbContext => { dbContext.UserAccounts.Add(existingWorkItem.Subscribers.ElementAt(0)); dbContext.WorkItems.Add(existingWorkItem); - await dbContext.SaveChangesAsync(); + return dbContext.SaveChangesAsync(); }); var requestBody = new @@ -68,11 +70,11 @@ public async Task Cannot_remove_from_ManyToMany_relationship() WorkItem existingWorkItem = _fakers.WorkItem.Generate(); existingWorkItem.Tags = _fakers.WorkTag.Generate(1).ToHashSet(); - await _testContext.RunOnDatabaseAsync(async dbContext => + await _testContext.RunOnDatabaseAsync(dbContext => { dbContext.WorkTags.Add(existingWorkItem.Tags.ElementAt(0)); dbContext.WorkItems.Add(existingWorkItem); - await dbContext.SaveChangesAsync(); + return dbContext.SaveChangesAsync(); }); var requestBody = new diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Updating/Relationships/ReplaceToManyRelationshipTests.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Updating/Relationships/ReplaceToManyRelationshipTests.cs index 2c78ccd..0d623d7 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Updating/Relationships/ReplaceToManyRelationshipTests.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Updating/Relationships/ReplaceToManyRelationshipTests.cs @@ -15,6 +15,8 @@ public ReplaceToManyRelationshipTests(IntegrationTestContext(); } @@ -25,11 +27,11 @@ public async Task Cannot_replace_OneToMany_relationship() WorkItem existingWorkItem = _fakers.WorkItem.Generate(); UserAccount existingSubscriber = _fakers.UserAccount.Generate(); - await _testContext.RunOnDatabaseAsync(async dbContext => + await _testContext.RunOnDatabaseAsync(dbContext => { dbContext.UserAccounts.Add(existingSubscriber); dbContext.WorkItems.Add(existingWorkItem); - await dbContext.SaveChangesAsync(); + return dbContext.SaveChangesAsync(); }); var requestBody = new @@ -68,11 +70,11 @@ public async Task Cannot_replace_ManyToMany_relationship() WorkItem existingWorkItem = _fakers.WorkItem.Generate(); WorkTag existingTag = _fakers.WorkTag.Generate(); - await _testContext.RunOnDatabaseAsync(async dbContext => + await _testContext.RunOnDatabaseAsync(dbContext => { dbContext.WorkTags.Add(existingTag); dbContext.WorkItems.Add(existingWorkItem); - await dbContext.SaveChangesAsync(); + return dbContext.SaveChangesAsync(); }); var requestBody = new diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Updating/Relationships/UpdateToOneRelationshipTests.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Updating/Relationships/UpdateToOneRelationshipTests.cs index 0e76c43..38168eb 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Updating/Relationships/UpdateToOneRelationshipTests.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Updating/Relationships/UpdateToOneRelationshipTests.cs @@ -15,6 +15,8 @@ public UpdateToOneRelationshipTests(IntegrationTestContext(); } @@ -25,11 +27,11 @@ public async Task Cannot_replace_ToOne_relationship() WorkItemGroup existingGroup = _fakers.WorkItemGroup.Generate(); RgbColor existingColor = _fakers.RgbColor.Generate(); - await _testContext.RunOnDatabaseAsync(async dbContext => + await _testContext.RunOnDatabaseAsync(dbContext => { dbContext.RgbColors.Add(existingColor); dbContext.Groups.Add(existingGroup); - await dbContext.SaveChangesAsync(); + return dbContext.SaveChangesAsync(); }); var requestBody = new diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Updating/Resources/ReplaceToManyRelationshipTests.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Updating/Resources/ReplaceToManyRelationshipTests.cs index ed39b18..fe61fa8 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Updating/Resources/ReplaceToManyRelationshipTests.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Updating/Resources/ReplaceToManyRelationshipTests.cs @@ -15,6 +15,8 @@ public ReplaceToManyRelationshipTests(IntegrationTestContext(); } @@ -25,11 +27,11 @@ public async Task Cannot_replace_OneToMany_relationship() WorkItem existingWorkItem = _fakers.WorkItem.Generate(); UserAccount existingSubscriber = _fakers.UserAccount.Generate(); - await _testContext.RunOnDatabaseAsync(async dbContext => + await _testContext.RunOnDatabaseAsync(dbContext => { dbContext.UserAccounts.Add(existingSubscriber); dbContext.WorkItems.Add(existingWorkItem); - await dbContext.SaveChangesAsync(); + return dbContext.SaveChangesAsync(); }); var requestBody = new @@ -79,11 +81,11 @@ public async Task Cannot_replace_ManyToMany_relationship() WorkItem existingWorkItem = _fakers.WorkItem.Generate(); WorkTag existingTag = _fakers.WorkTag.Generate(); - await _testContext.RunOnDatabaseAsync(async dbContext => + await _testContext.RunOnDatabaseAsync(dbContext => { dbContext.WorkTags.Add(existingTag); dbContext.WorkItems.Add(existingWorkItem); - await dbContext.SaveChangesAsync(); + return dbContext.SaveChangesAsync(); }); var requestBody = new diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Updating/Resources/UpdateResourceTests.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Updating/Resources/UpdateResourceTests.cs index 4faf659..6163c5e 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Updating/Resources/UpdateResourceTests.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Updating/Resources/UpdateResourceTests.cs @@ -16,15 +16,17 @@ public UpdateResourceTests(IntegrationTestContext(); testContext.UseController(); testContext.UseController(); testContext.UseController(); - testContext.ConfigureServicesAfterStartup(services => + testContext.ConfigureServices(services => { - services.AddResourceDefinition(); - services.AddResourceDefinition(); + services.AddResourceDefinition(); + services.AddResourceDefinition(); }); } @@ -34,10 +36,10 @@ public async Task Can_update_resource_without_attributes_or_relationships() // Arrange UserAccount existingUserAccount = _fakers.UserAccount.Generate(); - await _testContext.RunOnDatabaseAsync(async dbContext => + await _testContext.RunOnDatabaseAsync(dbContext => { dbContext.UserAccounts.Add(existingUserAccount); - await dbContext.SaveChangesAsync(); + return dbContext.SaveChangesAsync(); }); var requestBody = new @@ -81,10 +83,10 @@ public async Task Can_partially_update_resource_with_string_ID() WorkItemGroup existingGroup = _fakers.WorkItemGroup.Generate(); string newName = _fakers.WorkItemGroup.Generate().Name; - await _testContext.RunOnDatabaseAsync(async dbContext => + await _testContext.RunOnDatabaseAsync(dbContext => { dbContext.Groups.Add(existingGroup); - await dbContext.SaveChangesAsync(); + return dbContext.SaveChangesAsync(); }); var requestBody = new @@ -108,7 +110,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - string groupName = $"{newName}{ContainerTypeToHideFromAutoDiscovery.ImplicitlyChangingWorkItemGroupDefinition.Suffix}"; + string groupName = $"{newName}{ImplicitlyChangingWorkItemGroupDefinition.Suffix}"; responseDocument.Data.SingleValue.ShouldNotBeNull(); responseDocument.Data.SingleValue.Type.Should().Be("workItemGroups"); @@ -133,10 +135,10 @@ public async Task Can_completely_update_resource_with_string_ID() RgbColor existingColor = _fakers.RgbColor.Generate(); string newDisplayName = _fakers.RgbColor.Generate().DisplayName; - await _testContext.RunOnDatabaseAsync(async dbContext => + await _testContext.RunOnDatabaseAsync(dbContext => { dbContext.RgbColors.Add(existingColor); - await dbContext.SaveChangesAsync(); + return dbContext.SaveChangesAsync(); }); var requestBody = new @@ -177,10 +179,10 @@ public async Task Can_update_resource_without_side_effects() UserAccount existingUserAccount = _fakers.UserAccount.Generate(); UserAccount newUserAccount = _fakers.UserAccount.Generate(); - await _testContext.RunOnDatabaseAsync(async dbContext => + await _testContext.RunOnDatabaseAsync(dbContext => { dbContext.UserAccounts.Add(existingUserAccount); - await dbContext.SaveChangesAsync(); + return dbContext.SaveChangesAsync(); }); var requestBody = new @@ -223,10 +225,10 @@ public async Task Can_update_resource_with_side_effects() WorkItem existingWorkItem = _fakers.WorkItem.Generate(); string newDescription = _fakers.WorkItem.Generate().Description!; - await _testContext.RunOnDatabaseAsync(async dbContext => + await _testContext.RunOnDatabaseAsync(dbContext => { dbContext.WorkItems.Add(existingWorkItem); - await dbContext.SaveChangesAsync(); + return dbContext.SaveChangesAsync(); }); var requestBody = new @@ -251,7 +253,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - string itemDescription = $"{newDescription}{ContainerTypeToHideFromAutoDiscovery.ImplicitlyChangingWorkItemDefinition.Suffix}"; + string itemDescription = $"{newDescription}{ImplicitlyChangingWorkItemDefinition.Suffix}"; responseDocument.Data.SingleValue.ShouldNotBeNull(); responseDocument.Data.SingleValue.Type.Should().Be("workItems"); @@ -279,10 +281,10 @@ public async Task Can_update_resource_with_side_effects_with_primary_fieldset() WorkItem existingWorkItem = _fakers.WorkItem.Generate(); string newDescription = _fakers.WorkItem.Generate().Description!; - await _testContext.RunOnDatabaseAsync(async dbContext => + await _testContext.RunOnDatabaseAsync(dbContext => { dbContext.WorkItems.Add(existingWorkItem); - await dbContext.SaveChangesAsync(); + return dbContext.SaveChangesAsync(); }); var requestBody = new @@ -307,7 +309,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext => // Assert httpResponse.ShouldHaveStatusCode(HttpStatusCode.OK); - string itemDescription = $"{newDescription}{ContainerTypeToHideFromAutoDiscovery.ImplicitlyChangingWorkItemDefinition.Suffix}"; + string itemDescription = $"{newDescription}{ImplicitlyChangingWorkItemDefinition.Suffix}"; responseDocument.Data.SingleValue.ShouldNotBeNull(); responseDocument.Data.SingleValue.Type.Should().Be("workItems"); diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Updating/Resources/UpdateToOneRelationshipTests.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Updating/Resources/UpdateToOneRelationshipTests.cs index 2a0faf2..de4ddbc 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Updating/Resources/UpdateToOneRelationshipTests.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ReadWrite/Updating/Resources/UpdateToOneRelationshipTests.cs @@ -15,6 +15,8 @@ public UpdateToOneRelationshipTests(IntegrationTestContext(); } @@ -25,11 +27,11 @@ public async Task Cannot_create_ToOne_relationship() WorkItemGroup existingGroup = _fakers.WorkItemGroup.Generate(); RgbColor existingColor = _fakers.RgbColor.Generate(); - await _testContext.RunOnDatabaseAsync(async dbContext => + await _testContext.RunOnDatabaseAsync(dbContext => { dbContext.RgbColors.Add(existingColor); dbContext.Groups.Add(existingGroup); - await dbContext.SaveChangesAsync(); + return dbContext.SaveChangesAsync(); }); var requestBody = new diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ResourceDefinitions/Reading/ResourceDefinitionReadTests.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ResourceDefinitions/Reading/ResourceDefinitionReadTests.cs index d9b54c4..69bc808 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ResourceDefinitions/Reading/ResourceDefinitionReadTests.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ResourceDefinitions/Reading/ResourceDefinitionReadTests.cs @@ -3,6 +3,7 @@ using JsonApiDotNetCore.Configuration; using JsonApiDotNetCore.Serialization.Objects; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; using TestBuildingBlocks; using Xunit; @@ -17,14 +18,20 @@ public ResourceDefinitionReadTests(IntegrationTestContext(); testContext.UseController(); testContext.UseController(); - testContext.ConfigureServicesAfterStartup(services => + testContext.ConfigureServices(services => { - services.AddSingleton(); - services.AddSingleton(); + services.TryAddSingleton(); + services.TryAddSingleton(); + + services.AddResourceDefinition(); + services.AddResourceDefinition(); + services.AddResourceDefinition(); }); var options = (JsonApiOptions)testContext.Factory.Services.GetRequiredService(); @@ -293,10 +300,10 @@ public async Task Attribute_inclusion_from_resource_definition_is_applied_for_om Star star = _fakers.Star.Generate(); - await _testContext.RunOnDatabaseAsync(async dbContext => + await _testContext.RunOnDatabaseAsync(dbContext => { dbContext.Stars.Add(star); - await dbContext.SaveChangesAsync(); + return dbContext.SaveChangesAsync(); }); string route = $"/stars/{star.StringId}"; @@ -333,10 +340,10 @@ public async Task Attribute_inclusion_from_resource_definition_is_applied_for_fi Star star = _fakers.Star.Generate(); - await _testContext.RunOnDatabaseAsync(async dbContext => + await _testContext.RunOnDatabaseAsync(dbContext => { dbContext.Stars.Add(star); - await dbContext.SaveChangesAsync(); + return dbContext.SaveChangesAsync(); }); string route = $"/stars/{star.StringId}?fields[stars]=name,solarRadius"; @@ -374,10 +381,10 @@ public async Task Attribute_exclusion_from_resource_definition_is_applied_for_om Star star = _fakers.Star.Generate(); - await _testContext.RunOnDatabaseAsync(async dbContext => + await _testContext.RunOnDatabaseAsync(dbContext => { dbContext.Stars.Add(star); - await dbContext.SaveChangesAsync(); + return dbContext.SaveChangesAsync(); }); string route = $"/stars/{star.StringId}"; @@ -414,10 +421,10 @@ public async Task Attribute_exclusion_from_resource_definition_is_applied_for_fi Star star = _fakers.Star.Generate(); - await _testContext.RunOnDatabaseAsync(async dbContext => + await _testContext.RunOnDatabaseAsync(dbContext => { dbContext.Stars.Add(star); - await dbContext.SaveChangesAsync(); + return dbContext.SaveChangesAsync(); }); string route = $"/stars/{star.StringId}?fields[stars]=name,isVisibleFromEarth"; @@ -551,10 +558,10 @@ public async Task Queryable_parameter_handler_from_resource_definition_is_not_ap Planet planet = _fakers.Planet.Generate(); planet.Moons = _fakers.Moon.Generate(1).ToHashSet(); - await _testContext.RunOnDatabaseAsync(async dbContext => + await _testContext.RunOnDatabaseAsync(dbContext => { dbContext.Planets.Add(planet); - await dbContext.SaveChangesAsync(); + return dbContext.SaveChangesAsync(); }); string route = $"/planets/{planet.StringId}/moons?isLargerThanTheSun=false"; diff --git a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ResourceDefinitions/Reading/StarDefinition.cs b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ResourceDefinitions/Reading/StarDefinition.cs index 5ca6551..46632bd 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ResourceDefinitions/Reading/StarDefinition.cs +++ b/test/JsonApiDotNetCoreMongoDbTests/IntegrationTests/ResourceDefinitions/Reading/StarDefinition.cs @@ -26,11 +26,10 @@ public override SortExpression OnApplySort(SortExpression? existingSort) private SortExpression GetDefaultSortOrder() { - return CreateSortExpressionFromLambda(new PropertySortOrder - { + return CreateSortExpressionFromLambda([ (star => star.SolarMass, ListSortDirection.Descending), (star => star.SolarRadius, ListSortDirection.Descending) - }); + ]); } public override PaginationExpression OnApplyPagination(PaginationExpression? existingPagination) diff --git a/test/JsonApiDotNetCoreMongoDbTests/JsonApiDotNetCoreMongoDbTests.csproj b/test/JsonApiDotNetCoreMongoDbTests/JsonApiDotNetCoreMongoDbTests.csproj index b8d099f..d25aea3 100644 --- a/test/JsonApiDotNetCoreMongoDbTests/JsonApiDotNetCoreMongoDbTests.csproj +++ b/test/JsonApiDotNetCoreMongoDbTests/JsonApiDotNetCoreMongoDbTests.csproj @@ -1,8 +1,10 @@ - $(TargetFrameworkName) + net8.0;net6.0 + + diff --git a/test/TestBuildingBlocks/AssemblyInfo.cs b/test/TestBuildingBlocks/AssemblyInfo.cs index 82d1291..2af69d7 100644 --- a/test/TestBuildingBlocks/AssemblyInfo.cs +++ b/test/TestBuildingBlocks/AssemblyInfo.cs @@ -1,4 +1,4 @@ using System.Diagnostics.CodeAnalysis; -// https://github.com/coverlet-coverage/coverlet/blob/master/Documentation/MSBuildIntegration.md#excluding-from-coverage +// Justification: This assembly contains building blocks for writing tests. It does not contain code that ships. [assembly: ExcludeFromCodeCoverage] diff --git a/test/TestBuildingBlocks/IntegrationTest.cs b/test/TestBuildingBlocks/IntegrationTest.cs index 50fc3fd..2080a47 100644 --- a/test/TestBuildingBlocks/IntegrationTest.cs +++ b/test/TestBuildingBlocks/IntegrationTest.cs @@ -22,34 +22,34 @@ static IntegrationTest() ThrottleSemaphore = new SemaphoreSlim(maxConcurrentTestRuns); } - public async Task<(HttpResponseMessage httpResponse, TResponseDocument responseDocument)> ExecuteGetAsync(string requestUrl, + public Task<(HttpResponseMessage httpResponse, TResponseDocument responseDocument)> ExecuteGetAsync(string requestUrl, Action? setRequestHeaders = null) { - return await ExecuteRequestAsync(HttpMethod.Get, requestUrl, null, null, setRequestHeaders); + return ExecuteRequestAsync(HttpMethod.Get, requestUrl, null, null, setRequestHeaders); } - public async Task<(HttpResponseMessage httpResponse, TResponseDocument responseDocument)> ExecutePostAsync(string requestUrl, + public Task<(HttpResponseMessage httpResponse, TResponseDocument responseDocument)> ExecutePostAsync(string requestUrl, object requestBody, string contentType = HeaderConstants.MediaType, Action? setRequestHeaders = null) { - return await ExecuteRequestAsync(HttpMethod.Post, requestUrl, requestBody, contentType, setRequestHeaders); + return ExecuteRequestAsync(HttpMethod.Post, requestUrl, requestBody, contentType, setRequestHeaders); } - public async Task<(HttpResponseMessage httpResponse, TResponseDocument responseDocument)> ExecutePostAtomicAsync(string requestUrl, + public Task<(HttpResponseMessage httpResponse, TResponseDocument responseDocument)> ExecutePostAtomicAsync(string requestUrl, object requestBody, string contentType = HeaderConstants.AtomicOperationsMediaType, Action? setRequestHeaders = null) { - return await ExecuteRequestAsync(HttpMethod.Post, requestUrl, requestBody, contentType, setRequestHeaders); + return ExecuteRequestAsync(HttpMethod.Post, requestUrl, requestBody, contentType, setRequestHeaders); } - public async Task<(HttpResponseMessage httpResponse, TResponseDocument responseDocument)> ExecutePatchAsync(string requestUrl, + public Task<(HttpResponseMessage httpResponse, TResponseDocument responseDocument)> ExecutePatchAsync(string requestUrl, object requestBody, string contentType = HeaderConstants.MediaType, Action? setRequestHeaders = null) { - return await ExecuteRequestAsync(HttpMethod.Patch, requestUrl, requestBody, contentType, setRequestHeaders); + return ExecuteRequestAsync(HttpMethod.Patch, requestUrl, requestBody, contentType, setRequestHeaders); } - public async Task<(HttpResponseMessage httpResponse, TResponseDocument responseDocument)> ExecuteDeleteAsync(string requestUrl, + public Task<(HttpResponseMessage httpResponse, TResponseDocument responseDocument)> ExecuteDeleteAsync(string requestUrl, object? requestBody = null, string contentType = HeaderConstants.MediaType, Action? setRequestHeaders = null) { - return await ExecuteRequestAsync(HttpMethod.Delete, requestUrl, requestBody, contentType, setRequestHeaders); + return ExecuteRequestAsync(HttpMethod.Delete, requestUrl, requestBody, contentType, setRequestHeaders); } private async Task<(HttpResponseMessage httpResponse, TResponseDocument responseDocument)> ExecuteRequestAsync(HttpMethod method, @@ -110,9 +110,9 @@ static IntegrationTest() } } - public async Task InitializeAsync() + public Task InitializeAsync() { - await ThrottleSemaphore.WaitAsync(); + return ThrottleSemaphore.WaitAsync(); } public virtual Task DisposeAsync() diff --git a/test/TestBuildingBlocks/IntegrationTestContext.cs b/test/TestBuildingBlocks/IntegrationTestContext.cs index f97fd98..f479821 100644 --- a/test/TestBuildingBlocks/IntegrationTestContext.cs +++ b/test/TestBuildingBlocks/IntegrationTestContext.cs @@ -1,3 +1,4 @@ +using System.Reflection; using System.Text.Json; using EphemeralMongo; using JetBrains.Annotations; @@ -10,6 +11,7 @@ using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.AspNetCore.TestHost; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Hosting; using MongoDB.Driver; @@ -33,9 +35,9 @@ public class IntegrationTestContext : Integration { private readonly Lazy _runner; private readonly Lazy> _lazyFactory; + private readonly HashSet _resourceClrTypes = []; private readonly TestControllerProvider _testControllerProvider = new(); - - private Action? _afterServicesConfiguration; + private Action? _configureServices; protected override JsonSerializerOptions SerializerOptions { @@ -59,6 +61,16 @@ private IMongoRunner StartMongoDb() return MongoRunnerProvider.Instance.Get(); } + public void UseResourceTypesInNamespace(string? codeNamespace) + { + Assembly assembly = typeof(TStartup).Assembly; + + foreach (Type resourceClrType in ResourceTypeFinder.GetResourceClrTypesInNamespace(assembly, codeNamespace)) + { + _resourceClrTypes.Add(resourceClrType); + } + } + public void UseController() where TController : ControllerBase { @@ -74,27 +86,34 @@ private WebApplicationFactory CreateFactory() { var factory = new IntegrationTestWebApplicationFactory(); - factory.ConfigureServicesBeforeStartup(services => + factory.ConfigureServices(services => { + _configureServices?.Invoke(services); + services.ReplaceControllers(_testControllerProvider); - services.AddSingleton(_ => + services.TryAddSingleton(_ => { var client = new MongoClient(_runner.Value.ConnectionString); - return client.GetDatabase($"JsonApiDotNetCore_MongoDb_{new Random().Next()}_Test"); + return client.GetDatabase($"JsonApiDotNetCore_MongoDb_{Random.Shared.Next()}_Test"); }); - services.AddJsonApi(ConfigureJsonApiOptions, facade => facade.AddAssembly(typeof(TStartup).Assembly)); - services.AddJsonApiMongoDb(); + services.TryAddScoped(); - services.AddScoped(typeof(IResourceReadRepository<,>), typeof(MongoRepository<,>)); - services.AddScoped(typeof(IResourceWriteRepository<,>), typeof(MongoRepository<,>)); - services.AddScoped(typeof(IResourceRepository<,>), typeof(MongoRepository<,>)); + services.TryAddScoped(typeof(IResourceReadRepository<,>), typeof(MongoRepository<,>)); + services.TryAddScoped(typeof(IResourceWriteRepository<,>), typeof(MongoRepository<,>)); + services.TryAddScoped(typeof(IResourceRepository<,>), typeof(MongoRepository<,>)); - services.AddScoped(); - }); + services.AddJsonApi(ConfigureJsonApiOptions, resources: builder => + { + foreach (Type resourceClrType in _resourceClrTypes) + { + builder.Add(resourceClrType); + } + }); - factory.ConfigureServicesAfterStartup(_afterServicesConfiguration); + services.AddJsonApiMongoDb(); + }); // We have placed an appsettings.json in the TestBuildingBlock project folder and set the content root to there. Note that controllers // are not discovered in the content root but are registered manually using IntegrationTestContext.UseController. @@ -108,9 +127,9 @@ private void ConfigureJsonApiOptions(JsonApiOptions options) options.SerializerOptions.WriteIndented = true; } - public void ConfigureServicesAfterStartup(Action servicesConfiguration) + public void ConfigureServices(Action configureServices) { - _afterServicesConfiguration = servicesConfiguration; + _configureServices = configureServices; } public async Task RunOnDatabaseAsync(Func asyncAction) @@ -143,17 +162,11 @@ public override async Task DisposeAsync() private sealed class IntegrationTestWebApplicationFactory : WebApplicationFactory { - private Action? _beforeServicesConfiguration; - private Action? _afterServicesConfiguration; + private Action? _configureServices; - public void ConfigureServicesBeforeStartup(Action? servicesConfiguration) + public void ConfigureServices(Action? configureServices) { - _beforeServicesConfiguration = servicesConfiguration; - } - - public void ConfigureServicesAfterStartup(Action? servicesConfiguration) - { - _afterServicesConfiguration = servicesConfiguration; + _configureServices = configureServices; } protected override IHostBuilder CreateHostBuilder() @@ -165,21 +178,12 @@ protected override IHostBuilder CreateHostBuilder() .CreateDefaultBuilder(null) .ConfigureWebHostDefaults(webBuilder => { - webBuilder.ConfigureServices(services => - { - _beforeServicesConfiguration?.Invoke(services); - }); - + webBuilder.ConfigureServices(services => _configureServices?.Invoke(services)); webBuilder.UseStartup(); - - webBuilder.ConfigureServices(services => - { - _afterServicesConfiguration?.Invoke(services); - }); }); - // @formatter:keep_existing_linebreaks restore // @formatter:wrap_before_first_method_call restore + // @formatter:wrap_chained_method_calls restore } } } diff --git a/test/TestBuildingBlocks/MongoDbContextShim.cs b/test/TestBuildingBlocks/MongoDbContextShim.cs index 323af40..0521914 100644 --- a/test/TestBuildingBlocks/MongoDbContextShim.cs +++ b/test/TestBuildingBlocks/MongoDbContextShim.cs @@ -10,7 +10,7 @@ namespace TestBuildingBlocks; public abstract class MongoDbContextShim { private readonly IMongoDatabase _database; - private readonly List _dbSetShims = new(); + private readonly List _dbSetShims = []; protected MongoDbContextShim(IMongoDatabase database) { @@ -27,10 +27,10 @@ protected MongoDbSetShim Set() return dbSetShim; } - public async Task ClearTableAsync() + public Task ClearTableAsync() where TEntity : IMongoIdentifiable { - await _database.DropCollectionAsync(typeof(TEntity).Name); + return _database.DropCollectionAsync(typeof(TEntity).Name); } public async Task SaveChangesAsync(CancellationToken cancellation = default) diff --git a/test/TestBuildingBlocks/MongoDbSetShim.cs b/test/TestBuildingBlocks/MongoDbSetShim.cs index 7e58223..16e35d5 100644 --- a/test/TestBuildingBlocks/MongoDbSetShim.cs +++ b/test/TestBuildingBlocks/MongoDbSetShim.cs @@ -18,7 +18,7 @@ public sealed class MongoDbSetShim : MongoDbSetShim where TEntity : IMongoIdentifiable { private readonly IMongoCollection _collection; - private readonly List _entitiesToInsert = new(); + private readonly List _entitiesToInsert = []; internal MongoDbSetShim(IMongoCollection collection) { @@ -57,9 +57,9 @@ internal override async Task PersistAsync(CancellationToken cancellationToken) } } - public async Task ExecuteAsync(Func, Task> action) + public Task ExecuteAsync(Func, Task> action) { - await action(_collection); + return action(_collection); } public async Task FirstWithIdAsync(string? id, CancellationToken cancellationToken = default) @@ -79,13 +79,13 @@ public async Task FirstWithIdAsync(string? id, CancellationToken cancel return await _collection.AsQueryable().FirstOrDefaultAsync(document => Equals(document.Id, id), cancellationToken); } - public async Task> ToListAsync(CancellationToken cancellationToken = default) + public Task> ToListAsync(CancellationToken cancellationToken = default) { - return await _collection.AsQueryable().ToListAsync(cancellationToken); + return _collection.AsQueryable().ToListAsync(cancellationToken); } - public async Task> ToListWhereAsync(Expression> predicate, CancellationToken cancellationToken = default) + public Task> ToListWhereAsync(Expression> predicate, CancellationToken cancellationToken = default) { - return await _collection.AsQueryable().Where(predicate).ToListAsync(cancellationToken); + return _collection.AsQueryable().Where(predicate).ToListAsync(cancellationToken); } } diff --git a/test/TestBuildingBlocks/MongoRunnerProvider.cs b/test/TestBuildingBlocks/MongoRunnerProvider.cs index 9565815..c22b8d5 100644 --- a/test/TestBuildingBlocks/MongoRunnerProvider.cs +++ b/test/TestBuildingBlocks/MongoRunnerProvider.cs @@ -1,7 +1,5 @@ using EphemeralMongo; -#pragma warning disable AV1553 // Do not use optional parameters with default value null for strings, collections or tasks - namespace TestBuildingBlocks; // Based on https://gist.github.com/asimmon/612b2d54f1a0d2b4e1115590d456e0be. diff --git a/test/TestBuildingBlocks/ResourceTypeFinder.cs b/test/TestBuildingBlocks/ResourceTypeFinder.cs new file mode 100644 index 0000000..c4d6ecf --- /dev/null +++ b/test/TestBuildingBlocks/ResourceTypeFinder.cs @@ -0,0 +1,31 @@ +using System.Collections.Concurrent; +using System.Reflection; +using JsonApiDotNetCore.Resources; + +#pragma warning disable AV1008 // Class should not be static + +namespace TestBuildingBlocks; + +internal static class ResourceTypeFinder +{ + private static readonly ConcurrentDictionary> ResourceTypesPerAssembly = new(); + private static readonly ConcurrentDictionary> ResourceTypesPerNamespace = new(); + + public static IReadOnlySet GetResourceClrTypesInNamespace(Assembly assembly, string? codeNamespace) + { + IReadOnlySet resourceClrTypesInAssembly = ResourceTypesPerAssembly.GetOrAdd(assembly, GetResourceClrTypesInAssembly); + + string namespaceKey = codeNamespace ?? string.Empty; + return ResourceTypesPerNamespace.GetOrAdd(namespaceKey, _ => FilterTypesInNamespace(resourceClrTypesInAssembly, codeNamespace).ToHashSet()); + } + + private static IReadOnlySet GetResourceClrTypesInAssembly(Assembly assembly) + { + return assembly.GetTypes().Where(type => type.IsAssignableTo(typeof(IIdentifiable))).ToHashSet(); + } + + private static IEnumerable FilterTypesInNamespace(IEnumerable resourceClrTypesInAssembly, string? codeNamespace) + { + return resourceClrTypesInAssembly.Where(resourceClrType => resourceClrType.Namespace == codeNamespace); + } +} diff --git a/test/TestBuildingBlocks/TestBuildingBlocks.csproj b/test/TestBuildingBlocks/TestBuildingBlocks.csproj index 9d30f13..954ef72 100644 --- a/test/TestBuildingBlocks/TestBuildingBlocks.csproj +++ b/test/TestBuildingBlocks/TestBuildingBlocks.csproj @@ -1,8 +1,10 @@ - $(TargetFrameworkName) + net8.0;net6.0 + + diff --git a/tests.runsettings b/tests.runsettings new file mode 100644 index 0000000..db83eb9 --- /dev/null +++ b/tests.runsettings @@ -0,0 +1,16 @@ + + + + true + + + + + + ObsoleteAttribute,GeneratedCodeAttribute + true + + + + + pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy